mirror of https://github.com/grafana/grafana.git
Remove drone & dead code in pkg/build; update go modules (#109935)
* remove drone & dead code in pkg/build; update go modules * remove .drone.star * Remove drone scripts and drone references in Makefile * make update-workspace * remove deadcode tool * Remove daggerbuild/scripts: deadcode * Remove drone files / folders in CODEOWNERS * make update-workspace * remove more dead code
This commit is contained in:
parent
196506a484
commit
7c2945bb54
38
.drone.star
38
.drone.star
|
@ -1,38 +0,0 @@
|
|||
# To generate the .drone.yml file:
|
||||
# 1. Modify the *.star definitions
|
||||
# 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/main.star", "main_pipelines")
|
||||
load(
|
||||
"scripts/drone/events/release.star",
|
||||
"publish_artifacts_pipelines",
|
||||
"publish_npm_pipelines",
|
||||
"publish_packages_pipeline",
|
||||
)
|
||||
load("scripts/drone/events/rrc-patch.star", "rrc_patch_pipelines")
|
||||
load(
|
||||
"scripts/drone/pipelines/publish_images.star",
|
||||
"publish_image_pipelines_public",
|
||||
)
|
||||
load(
|
||||
"scripts/drone/rgm.star",
|
||||
"rgm",
|
||||
)
|
||||
load("scripts/drone/vault.star", "secrets")
|
||||
|
||||
def main(_ctx):
|
||||
return (
|
||||
main_pipelines() +
|
||||
rrc_patch_pipelines() +
|
||||
publish_image_pipelines_public() +
|
||||
publish_artifacts_pipelines("public") +
|
||||
publish_npm_pipelines() +
|
||||
publish_packages_pipeline() +
|
||||
rgm() +
|
||||
secrets()
|
||||
)
|
1880
.drone.yml
1880
.drone.yml
File diff suppressed because it is too large
Load Diff
|
@ -328,9 +328,6 @@
|
|||
|
||||
|
||||
# Continuous Integration
|
||||
.drone.yml @grafana/grafana-developer-enablement-squad
|
||||
.drone.star @grafana/grafana-developer-enablement-squad
|
||||
/scripts/drone/ @grafana/grafana-developer-enablement-squad
|
||||
/pkg/build/ @grafana/grafana-developer-enablement-squad
|
||||
/.dockerignore @grafana/grafana-developer-enablement-squad
|
||||
/Dockerfile @grafana/grafana-developer-enablement-squad
|
||||
|
|
19
Makefile
19
Makefile
|
@ -524,25 +524,6 @@ gen-ts:
|
|||
tscriptify -interface -package=github.com/grafana/grafana/pkg/services/live/pipeline -import="import { FieldConfig } from '@grafana/data'" -target=public/app/features/live/pipeline/models.gen.ts pkg/services/live/pipeline/config.go
|
||||
go mod tidy
|
||||
|
||||
# This repository's configuration is protected (https://readme.drone.io/signature/).
|
||||
# Use this make target to regenerate the configuration YAML files when
|
||||
# you modify starlark files.
|
||||
.PHONY: drone
|
||||
drone: $(DRONE)
|
||||
bash scripts/drone/env-var-check.sh
|
||||
$(DRONE) starlark --format
|
||||
$(DRONE) lint .drone.yml --trusted
|
||||
$(DRONE) --server https://drone.grafana.net sign --save grafana/grafana
|
||||
|
||||
# Generate an Emacs tags table (https://www.gnu.org/software/emacs/manual/html_node/emacs/Tags-Tables.html) for Starlark files.
|
||||
.PHONY: scripts/drone/TAGS
|
||||
scripts/drone/TAGS: $(shell find scripts/drone -name '*.star')
|
||||
etags --lang none --regex="/def \(\w+\)[^:]+:/\1/" --regex="/\s*\(\w+\) =/\1/" $^ -o $@
|
||||
|
||||
.PHONY: format-drone
|
||||
format-drone:
|
||||
buildifier --lint=fix -r scripts/drone
|
||||
|
||||
.PHONY: go-race-is-enabled
|
||||
go-race-is-enabled:
|
||||
@if [ -n "$(GO_RACE)" ]; then \
|
||||
|
|
|
@ -82,13 +82,14 @@ require (
|
|||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
|
||||
|
|
|
@ -252,8 +252,8 @@ go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
|
|||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
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.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
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=
|
||||
|
@ -270,8 +270,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
|
@ -288,14 +288,14 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -308,8 +308,8 @@ golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtn
|
|||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
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/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
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=
|
||||
|
|
|
@ -110,15 +110,15 @@ require (
|
|||
go.opentelemetry.io/proto/otlp v1.7.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
|
||||
golang.org/x/mod v0.26.0 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/mod v0.27.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.35.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
|
||||
|
|
|
@ -314,15 +314,13 @@ golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ
|
|||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
|
||||
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.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
|
||||
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
|
||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||
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-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -341,14 +339,11 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -356,8 +351,7 @@ golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3
|
|||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
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/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
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=
|
||||
|
|
|
@ -47,11 +47,11 @@ require (
|
|||
go.opentelemetry.io/otel v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
|
|
|
@ -122,8 +122,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -132,14 +132,14 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
|
@ -309,17 +309,17 @@ require (
|
|||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/crypto v0.40.0 // indirect
|
||||
golang.org/x/crypto v0.41.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
|
||||
golang.org/x/mod v0.26.0 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/mod v0.27.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.35.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
|
||||
gonum.org/v1/gonum v0.16.0 // indirect
|
||||
|
|
|
@ -1367,8 +1367,8 @@ golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0
|
|||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
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=
|
||||
|
@ -1410,8 +1410,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
|
|||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
|
||||
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
|
||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||
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=
|
||||
|
@ -1470,8 +1470,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -1609,8 +1609,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
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/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
|
@ -1618,8 +1618,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
|||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
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=
|
||||
|
@ -1633,8 +1633,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
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=
|
||||
|
@ -1703,8 +1703,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
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=
|
||||
|
|
|
@ -65,13 +65,14 @@ require (
|
|||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.7.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
|
||||
|
|
|
@ -159,8 +159,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -171,22 +171,22 @@ golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
|||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
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/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
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=
|
||||
|
|
|
@ -65,13 +65,14 @@ require (
|
|||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.7.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
|
||||
|
|
|
@ -159,8 +159,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -171,22 +171,22 @@ golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
|||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
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/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
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=
|
||||
|
|
|
@ -71,14 +71,15 @@ require (
|
|||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.7.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/crypto v0.40.0 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/crypto v0.41.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
|
||||
|
|
|
@ -171,8 +171,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
|
@ -185,8 +185,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -206,23 +206,23 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
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/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -231,8 +231,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
|
|||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
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=
|
||||
|
|
|
@ -55,12 +55,13 @@ require (
|
|||
go.opentelemetry.io/otel v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
|
|
|
@ -130,8 +130,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -140,22 +140,22 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
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/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
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=
|
||||
|
|
|
@ -52,11 +52,11 @@ require (
|
|||
go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
|
|
|
@ -134,8 +134,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -144,14 +144,14 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
|
@ -66,13 +66,14 @@ require (
|
|||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.7.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
|
||||
|
|
|
@ -159,8 +159,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -171,22 +171,22 @@ golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
|||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
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/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
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=
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
# Making changes to the Drone pipeline
|
||||
|
||||
> Only members of the Grafana organization can make changes to the Drone pipeline.
|
||||
|
||||
The Drone pipelines are built with [Starlark](https://github.com/bazelbuild/starlark), a similar language to Python. The Starlark files are located in [`scripts/drone`](https://github.com/grafana/grafana/tree/main/scripts/drone).
|
||||
|
||||
## Drone setup
|
||||
|
||||
1. Set environment variables `DRONE_SERVER` and `DRONE_TOKEN` found in your [Drone account](https://drone.grafana.net/account). These environment variables are used to verify that only Grafana employees can make changes to the pipelines.
|
||||
1. Install [buildifier](https://github.com/bazelbuild/buildtools/blob/master/buildifier/README.md), and use it to format the Starlark files you want to edit.
|
||||
|
||||
## Drone development
|
||||
|
||||
1. Open a pull request where you can do test runs for your changes. If you need to experiment with secrets, create a pull request in the [`grafana-ci-sandbox repo`](https://github.com/grafana/grafana-ci-sandbox) before opening a pull request in the main repo.
|
||||
1. Run `make drone` after making changes to the Starlark files. This builds the `.drone.yml` file.
|
||||
|
||||
For further questions, reach out to the `grafana-release-guild` squad.
|
14
go.mod
14
go.mod
|
@ -197,15 +197,15 @@ require (
|
|||
go.uber.org/zap v1.27.0 // @grafana/identity-access-team
|
||||
gocloud.dev v0.42.0 // @grafana/grafana-app-platform-squad
|
||||
gocloud.dev/secrets/hashivault v0.42.0 // @grafana/grafana-operator-experience-squad
|
||||
golang.org/x/crypto v0.40.0 // @grafana/grafana-backend-group
|
||||
golang.org/x/crypto v0.41.0 // @grafana/grafana-backend-group
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // @grafana/alerting-backend
|
||||
golang.org/x/mod v0.26.0 // indirect; @grafana/grafana-backend-group
|
||||
golang.org/x/net v0.42.0 // @grafana/oss-big-tent @grafana/partner-datasources
|
||||
golang.org/x/mod v0.27.0 // indirect; @grafana/grafana-backend-group
|
||||
golang.org/x/net v0.43.0 // @grafana/oss-big-tent @grafana/partner-datasources
|
||||
golang.org/x/oauth2 v0.30.0 // @grafana/identity-access-team
|
||||
golang.org/x/sync v0.16.0 // @grafana/alerting-backend
|
||||
golang.org/x/text v0.27.0 // @grafana/grafana-backend-group
|
||||
golang.org/x/text v0.28.0 // @grafana/grafana-backend-group
|
||||
golang.org/x/time v0.11.0 // @grafana/grafana-backend-group
|
||||
golang.org/x/tools v0.35.0 // indirect; @grafana/grafana-as-code
|
||||
golang.org/x/tools v0.36.0 // indirect; @grafana/grafana-as-code
|
||||
gonum.org/v1/gonum v0.16.0 // @grafana/oss-big-tent
|
||||
google.golang.org/api v0.235.0 // @grafana/grafana-backend-group
|
||||
google.golang.org/grpc v1.74.2 // @grafana/plugins-platform-backend
|
||||
|
@ -603,8 +603,8 @@ require (
|
|||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
|
||||
|
|
28
go.sum
28
go.sum
|
@ -2687,8 +2687,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
|
|||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
|
@ -2752,8 +2752,8 @@ golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
|
||||
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
|
||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
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=
|
||||
|
@ -2839,8 +2839,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
|||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -3036,8 +3036,8 @@ golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
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=
|
||||
|
@ -3057,8 +3057,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
|||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
|
||||
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
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=
|
||||
|
@ -3081,8 +3081,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
|||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
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=
|
||||
|
@ -3168,8 +3168,8 @@ golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
|||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
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=
|
||||
|
|
30
go.work.sum
30
go.work.sum
|
@ -529,6 +529,8 @@ github.com/Azure/go-amqp v1.0.5 h1:po5+ljlcNSU8xtapHTe8gIc8yHxCzC03E8afH2g1ftU=
|
|||
github.com/Azure/go-amqp v1.0.5/go.mod h1:vZAogwdrkbyK3Mla8m/CxSc/aKdnTZ4IbPxl51Y5WZE=
|
||||
github.com/Azure/go-amqp v1.4.0 h1:Xj3caqi4comOF/L1Uc5iuBxR/pB6KumejC01YQOqOR4=
|
||||
github.com/Azure/go-amqp v1.4.0/go.mod h1:vZAogwdrkbyK3Mla8m/CxSc/aKdnTZ4IbPxl51Y5WZE=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.5.13 h1:Ov8avRZi2vmrE2JcXw+tu5K/yB41r7xK9GZDiBF7NdM=
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.5.13/go.mod h1:5BAVfWLWXihP47vYrPuBKKf4cS0bXI+KM9Qx6ETDJYo=
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 h1:w77/uPk80ZET2F+AfQExZyEWtn+0Rk/uw17m9fv5Ajc=
|
||||
|
@ -629,8 +631,6 @@ github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3 h1:ZSTrOEhi
|
|||
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 h1:G1bPvciwNyF7IUmKXNt9Ak3m6u9DE1rF+RmtIkBpVdA=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/atc0005/go-teams-notify/v2 v2.13.0 h1:nbDeHy89NjYlF/PEfLVF6lsserY9O5SnN1iOIw3AxXw=
|
||||
github.com/atc0005/go-teams-notify/v2 v2.13.0/go.mod h1:WSv9moolRsBcpZbwEf6gZxj7h0uJlJskJq5zkEWKO8Y=
|
||||
github.com/aws/aws-lambda-go v1.47.0 h1:0H8s0vumYx/YKs4sE7YM0ktwL2eWse+kfopsRI1sXVI=
|
||||
|
@ -641,8 +641,6 @@ github.com/aws/aws-sdk-go-v2/service/kinesis v1.33.0 h1:JPXkrQk5OS/+Q81fKH97Ll/V
|
|||
github.com/aws/aws-sdk-go-v2/service/kinesis v1.33.0/go.mod h1:dJngkoVMrq0K7QvRkdRZYM4NUp6cdWa2GBdpm8zoY8U=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.35.3 h1:UPTdlTOwWUX49fVi7cymEN6hDqCwe3LNv1vi7TXUutk=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.35.3/go.mod h1:gjDP16zn+WWalyaUqwCCioQ8gU8lzttCCc9jYsiQI/8=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.38.1 h1:tecq7+mAav5byF+Mr+iONJnCBf4B4gon8RSp4BrweSc=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.38.1/go.mod h1:cQn6tAF77Di6m4huxovNM7NVAozWTZLsDRp9t8Z/WYk=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.4 h1:NgRFYyFpiMD62y4VPXh4DosPFbZd4vdMVBWKk0VmWXc=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.4/go.mod h1:TKKN7IQoM7uTnyuFm9bm9cw5P//ZYTl4m3htBWQ1G/c=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.2 h1:vlYXbindmagyVA3RS2SPd47eKZ00GZZQcr+etTviHtc=
|
||||
|
@ -679,6 +677,8 @@ github.com/blevesearch/snowball v0.6.1 h1:cDYjn/NCH+wwt2UdehaLpr2e4BwLIjN4V/TdLs
|
|||
github.com/blevesearch/snowball v0.6.1/go.mod h1:ZF0IBg5vgpeoUhnMza2v0A/z8m1cWPlwhke08LpNusg=
|
||||
github.com/blevesearch/stempel v0.2.0 h1:CYzVPaScODMvgE9o+kf6D4RJ/VRomyi9uHF+PtB+Afc=
|
||||
github.com/blevesearch/stempel v0.2.0/go.mod h1:wjeTHqQv+nQdbPuJ/YcvOjTInA2EIc6Ks1FoSUzSLvc=
|
||||
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
|
||||
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||
|
@ -731,6 +731,8 @@ github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJP
|
|||
github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4=
|
||||
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
|
||||
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
|
||||
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
|
||||
github.com/coreos/etcd v3.3.27+incompatible h1:QIudLb9KeBsE5zyYxd1mjzRSkzLg9Wf9QlRwFgd6oTA=
|
||||
|
@ -751,6 +753,7 @@ github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHf
|
|||
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
|
||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/creasty/defaults v1.8.0 h1:z27FJxCAa0JKt3utc0sCImAEb+spPucmKoOdLHvHYKk=
|
||||
|
@ -794,6 +797,7 @@ github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E
|
|||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c=
|
||||
github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
|
||||
github.com/docker/distribution v2.7.0+incompatible h1:neUDAlf3wX6Ml4HdqTrbcOHXtfRN0TFIwt6YFL7N9RU=
|
||||
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
|
||||
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
|
||||
|
@ -806,6 +810,8 @@ github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81 h1:7/v8q9X
|
|||
github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81/go.mod h1:siLfyv2c92W1eN/R4QqG/+RjjX5W2+gCTRjZxBjI3TY=
|
||||
github.com/dolthub/swiss v0.2.1 h1:gs2osYs5SJkAaH5/ggVJqXQxRXtWshF6uE0lgR/Y3Gw=
|
||||
github.com/dolthub/swiss v0.2.1/go.mod h1:8AhKZZ1HK7g18j7v7k6c5cYIGEZJcPn0ARsai8cUrh0=
|
||||
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-20220929084810-72602997d16f h1:/jEs7lulqVO2u1+XI5rW4oFwIIusxuDOVKD9PAzlW2E=
|
||||
github.com/drone/funcmap v0.0.0-20220929084810-72602997d16f/go.mod h1:nDRkX7PHq+p39AD5/usv3KZMerxZTYU/9rfLS5IDspU=
|
||||
github.com/drone/signal v1.0.0 h1:NrnM2M/4yAuU/tXs6RP1a1ZfxnaHwYkd0kJurA1p6uI=
|
||||
|
@ -859,6 +865,7 @@ github.com/fsouza/fake-gcs-server v1.52.2/go.mod h1:47HKyIkz6oLTes1R8vEaHLwXfzYs
|
|||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/getkin/kin-openapi v0.128.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
|
@ -988,8 +995,6 @@ github.com/grafana/grafana-app-sdk/logging v0.39.1/go.mod h1:WhDENSnaGHtyVVwZGVn
|
|||
github.com/grafana/grafana-app-sdk/logging v0.40.0/go.mod h1:otUD9XpJD7A5sCLb8mcs9hIXGdeV6lnhzVwe747g4RU=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.40.3 h1:2VXsXXEQiqAavRP8wusRDB6rDqf5lufP7A6NfjELqPE=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.40.3/go.mod h1:otUD9XpJD7A5sCLb8mcs9hIXGdeV6lnhzVwe747g4RU=
|
||||
github.com/grafana/grafana-app-sdk/plugin v0.40.3 h1:uH0oFZnYOUL+OXcyhd5NVYwoM+Wa0WUXvZ2Om1M91r0=
|
||||
github.com/grafana/grafana-app-sdk/plugin v0.40.3/go.mod h1:+ylwE0P8WgPu5zURK5aDnVJpwRpuK3573rwrVV28qzQ=
|
||||
github.com/grafana/grafana-app-sdk/plugin v0.41.0 h1:ShUvGpAVzM3UxcsfwS6l/lwW4ytDeTbCQXf8w2P8Yp8=
|
||||
github.com/grafana/grafana-app-sdk/plugin v0.41.0/go.mod h1:YIhimVfAqtOp3kdhxOanaSZjypVKh/bYxf9wfFfhDm0=
|
||||
github.com/grafana/grafana-aws-sdk v0.38.2 h1:TzQD0OpWsNjtldi5G5TLDlBRk8OyDf+B5ujcoAu4Dp0=
|
||||
|
@ -1203,10 +1208,10 @@ github.com/mitchellh/gox v0.4.0 h1:lfGJxY7ToLJQjHHwi0EX6uYBdK78egf954SQl13PQJc=
|
|||
github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY=
|
||||
github.com/mithrandie/readline-csvq v1.3.0 h1:VTJEOGouJ8j27jJCD4kBBbNTxM0OdBvE1aY1tMhlqE8=
|
||||
github.com/mithrandie/readline-csvq v1.3.0/go.mod h1:FKyYqDgf/G4SNov7SMFXRWO6LQLXIOeTog/NB97FZl0=
|
||||
github.com/moby/moby v27.5.1+incompatible h1:/pN59F/t3U7Q4FPzV88nzqf7Fp0qqCSL2KzhZaiKcKw=
|
||||
github.com/moby/moby v27.5.1+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
|
||||
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
||||
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
|
||||
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
|
||||
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
|
||||
github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
|
||||
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||
|
@ -1215,11 +1220,14 @@ github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
|
|||
github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU=
|
||||
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
|
||||
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/mostynb/go-grpc-compression v1.2.3 h1:42/BKWMy0KEJGSdWvzqIyOZ95YcR9mLPqKctH7Uo//I=
|
||||
github.com/mostynb/go-grpc-compression v1.2.3/go.mod h1:AghIxF3P57umzqM9yz795+y1Vjs47Km/Y2FE6ouQ7Lg=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
|
||||
github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8 h1:P48LjvUQpTReR3TQRbxSeSBsMXzfK0uol7eRcr7VBYQ=
|
||||
github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A=
|
||||
github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM=
|
||||
|
@ -1740,6 +1748,8 @@ golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 h1:zf5N6UOrA487eEFacMe
|
|||
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0=
|
||||
golang.org/x/telemetry v0.0.0-20250710130107-8d8967aff50b h1:DU+gwOBXU+6bO0sEyO7o/NeMlxZxCZEvI7v+J4a1zRQ=
|
||||
golang.org/x/telemetry v0.0.0-20250710130107-8d8967aff50b/go.mod h1:4ZwOYna0/zsOKwuR5X/m0QFOJpSZvAxFfkQT+Erd9D4=
|
||||
golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488 h1:3doPGa+Gg4snce233aCWnbZVFsyFMo/dR40KK/6skyE=
|
||||
golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488/go.mod h1:fGb/2+tgXXjhjHsTNdVEEMZNWA0quBnfrO+AfoDSAKw=
|
||||
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
|
@ -1863,6 +1873,8 @@ gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg
|
|||
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
|
||||
gopkg.in/vmihailenco/msgpack.v2 v2.9.2 h1:gjPqo9orRVlSAH/065qw3MsFCDpH7fa1KpiizXyllY4=
|
||||
gopkg.in/vmihailenco/msgpack.v2 v2.9.2/go.mod h1:/3Dn1Npt9+MYyLpYYXjInO/5jvMLamn+AEGwNEOatn8=
|
||||
gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
|
||||
gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||
honnef.co/go/tools v0.3.2 h1:ytYb4rOqyp1TSa2EPvNVwtPQJctSELKaMyLfqNP4+34=
|
||||
honnef.co/go/tools v0.3.2/go.mod h1:jzwdWgg7Jdq75wlfblQxO4neNaFFSvgc1tD5Wv8U0Yw=
|
||||
howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=
|
||||
|
|
|
@ -137,17 +137,17 @@ require (
|
|||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/crypto v0.40.0 // indirect
|
||||
golang.org/x/crypto v0.41.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
|
||||
golang.org/x/mod v0.26.0 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/mod v0.27.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.35.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
|
||||
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
|
||||
|
|
|
@ -403,8 +403,8 @@ go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
|
|||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
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.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
|
||||
|
@ -414,8 +414,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
|||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
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.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
|
||||
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
|
||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||
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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -425,8 +425,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
|
@ -451,14 +451,14 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -472,8 +472,8 @@ golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtn
|
|||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
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/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
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=
|
||||
|
|
|
@ -43,11 +43,11 @@ require (
|
|||
go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/crypto v0.40.0 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/crypto v0.41.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/grpc v1.74.2 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
|
|
|
@ -96,8 +96,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
|
@ -110,8 +110,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -129,8 +129,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
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/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
|
@ -142,8 +142,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
|
|
|
@ -82,15 +82,15 @@ require (
|
|||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/crypto v0.40.0 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/crypto v0.41.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.35.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
|
||||
|
|
|
@ -240,8 +240,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
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=
|
||||
|
@ -264,8 +264,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
|
@ -291,23 +291,23 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
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/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -322,8 +322,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
|
|||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
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=
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package build
|
|
@ -1,127 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
"github.com/grafana/grafana/pkg/build/docker"
|
||||
"github.com/grafana/grafana/pkg/build/gcloud"
|
||||
)
|
||||
|
||||
const (
|
||||
alpine = "alpine"
|
||||
ubuntu = "ubuntu"
|
||||
)
|
||||
|
||||
// GetImageFiles returns the list of image (.img, but should be .tar because they are tar archives) files that are
|
||||
// created in the 'tag' process and stored in the prerelease bucket, waiting to be released.
|
||||
func GetImageFiles(grafana string, version string, architectures []config.Architecture) []string {
|
||||
bases := []string{alpine, ubuntu}
|
||||
images := []string{}
|
||||
for _, base := range bases {
|
||||
for _, arch := range architectures {
|
||||
image := fmt.Sprintf("%s-%s-%s.img", grafana, version, arch)
|
||||
if base == "ubuntu" {
|
||||
image = fmt.Sprintf("%s-%s-ubuntu-%s.img", grafana, version, arch)
|
||||
}
|
||||
|
||||
images = append(images, image)
|
||||
}
|
||||
}
|
||||
|
||||
return images
|
||||
}
|
||||
|
||||
func FetchImages(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
|
||||
}
|
||||
|
||||
buildConfig, err := config.GetBuildConfig(metadata.ReleaseMode.Mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg := docker.Config{
|
||||
Archs: buildConfig.Docker.Architectures,
|
||||
Distribution: buildConfig.Docker.Distribution,
|
||||
Bucket: buildConfig.Docker.PrereleaseBucket,
|
||||
Edition: c.String("edition"),
|
||||
Tag: metadata.GrafanaVersion,
|
||||
}
|
||||
|
||||
grafana := "grafana"
|
||||
if cfg.Edition == "enterprise" {
|
||||
grafana = "grafana-enterprise"
|
||||
}
|
||||
if cfg.Edition == "enterprise2" {
|
||||
grafana = "grafana-enterprise2"
|
||||
}
|
||||
if cfg.Edition == "grafana" || cfg.Edition == "oss" {
|
||||
grafana = "grafana-oss"
|
||||
}
|
||||
|
||||
baseURL := fmt.Sprintf("gs://%s/%s/", cfg.Bucket, cfg.Tag)
|
||||
images := GetImageFiles(grafana, cfg.Tag, cfg.Archs)
|
||||
|
||||
log.Printf("Fetching images [%v]", images)
|
||||
|
||||
if err := gcloud.ActivateServiceAccount(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := DownloadImages(baseURL, images, "."); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := LoadImages(images, "."); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadImages uses the `docker load -i` command to load the image tar file into the docker daemon so that it can be
|
||||
// tagged and pushed.
|
||||
func LoadImages(images []string, source string) error {
|
||||
p := filepath.Clean(source)
|
||||
for _, image := range images {
|
||||
image := filepath.Join(p, image)
|
||||
log.Println("Loading image", image)
|
||||
//nolint:gosec
|
||||
cmd := exec.Command("docker", "load", "-i", image)
|
||||
cmd.Dir = "."
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Printf("out: %s\n", out)
|
||||
return fmt.Errorf("error loading image: %q", err)
|
||||
}
|
||||
log.Println("Loaded image", image)
|
||||
}
|
||||
log.Println("Images successfully loaded!")
|
||||
return nil
|
||||
}
|
||||
|
||||
func DownloadImages(baseURL string, images []string, destination string) error {
|
||||
for _, image := range images {
|
||||
p := baseURL + image
|
||||
log.Println("Downloading image", p)
|
||||
//nolint:gosec
|
||||
cmd := exec.Command("gsutil", "-m", "cp", "-r", p, destination)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to download: %w\n%s", err, out)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetImageFiles(t *testing.T) {
|
||||
var (
|
||||
architectures = []config.Architecture{
|
||||
config.ArchAMD64,
|
||||
config.ArchARM64,
|
||||
config.ArchARMv7,
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("1.2.3", func(t *testing.T) {
|
||||
expect := []string{
|
||||
"grafana-oss-1.2.3-amd64.img",
|
||||
"grafana-oss-1.2.3-arm64.img",
|
||||
"grafana-oss-1.2.3-armv7.img",
|
||||
"grafana-oss-1.2.3-ubuntu-amd64.img",
|
||||
"grafana-oss-1.2.3-ubuntu-arm64.img",
|
||||
"grafana-oss-1.2.3-ubuntu-armv7.img",
|
||||
}
|
||||
|
||||
res := GetImageFiles("grafana-oss", "1.2.3", architectures)
|
||||
|
||||
require.Equal(t, expect, res)
|
||||
})
|
||||
|
||||
t.Run("1.2.3+example-01", func(t *testing.T) {
|
||||
expect := []string{
|
||||
"grafana-oss-1.2.3+example-01-amd64.img",
|
||||
"grafana-oss-1.2.3+example-01-arm64.img",
|
||||
"grafana-oss-1.2.3+example-01-armv7.img",
|
||||
"grafana-oss-1.2.3+example-01-ubuntu-amd64.img",
|
||||
"grafana-oss-1.2.3+example-01-ubuntu-arm64.img",
|
||||
"grafana-oss-1.2.3+example-01-ubuntu-armv7.img",
|
||||
}
|
||||
|
||||
res := GetImageFiles("grafana-oss", "1.2.3+example-01", architectures)
|
||||
|
||||
require.Equal(t, expect, res)
|
||||
})
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package main
|
||||
|
||||
import "github.com/urfave/cli/v2"
|
||||
|
||||
var (
|
||||
jobsFlag = cli.IntFlag{
|
||||
Name: "jobs",
|
||||
Usage: "Number of parallel jobs",
|
||||
}
|
||||
buildIDFlag = cli.StringFlag{
|
||||
Name: "build-id",
|
||||
Usage: "Optionally supply a build ID to be part of the version",
|
||||
}
|
||||
editionFlag = cli.StringFlag{
|
||||
Name: "edition",
|
||||
Usage: "The edition of Grafana to build (oss or enterprise)",
|
||||
Value: "oss",
|
||||
}
|
||||
triesFlag = cli.IntFlag{
|
||||
Name: "tries",
|
||||
Usage: "Specify number of tries before failing",
|
||||
Value: 1,
|
||||
}
|
||||
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",
|
||||
}
|
||||
)
|
|
@ -1,406 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"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/gcom"
|
||||
"github.com/grafana/grafana/pkg/build/packaging"
|
||||
"github.com/grafana/grafana/pkg/build/versions"
|
||||
)
|
||||
|
||||
const grafanaAPI = "https://grafana.com/api"
|
||||
|
||||
var httpClient = http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: func(dialer *net.Dialer) func(context.Context, string, string) (net.Conn, error) {
|
||||
return dialer.DialContext
|
||||
}(&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}),
|
||||
ForceAttemptHTTP2: true,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
},
|
||||
}
|
||||
|
||||
// GrafanaCom implements the sub-command "grafana-com".
|
||||
func GrafanaCom(c *cli.Context) error {
|
||||
bucketStr := c.String("src-bucket")
|
||||
edition := config.Edition(c.String("edition"))
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
releaseMode, err := metadata.GetReleaseMode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
version := metadata.GrafanaVersion
|
||||
semver := versions.ParseSemver(version)
|
||||
if releaseMode.Mode == config.Cronjob {
|
||||
gcs, err := storage.New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bucket := gcs.Bucket(bucketStr)
|
||||
latestMainVersion, err := storage.GetLatestMainBuild(c.Context, bucket, filepath.Join(string(edition), "main"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
version = latestMainVersion
|
||||
}
|
||||
|
||||
dryRun := c.Bool("dry-run")
|
||||
simulateRelease := c.Bool("simulate-release")
|
||||
// Test release mode and dryRun imply simulateRelease
|
||||
if releaseMode.IsTest || dryRun {
|
||||
simulateRelease = true
|
||||
}
|
||||
|
||||
grafanaAPIKey := strings.TrimSpace(os.Getenv("GRAFANA_COM_API_KEY"))
|
||||
if grafanaAPIKey == "" {
|
||||
return cli.Exit("the environment variable GRAFANA_COM_API_KEY must be set", 1)
|
||||
}
|
||||
|
||||
pkgjson, err := getPackageJSON()
|
||||
if err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
|
||||
whatsNewURL, releaseNotesURL, err := getReleaseURLs(semver, pkgjson)
|
||||
if err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
|
||||
// TODO: Verify config values
|
||||
cfg := packaging.PublishConfig{
|
||||
Config: config.Config{
|
||||
Version: version,
|
||||
},
|
||||
Edition: edition,
|
||||
ReleaseMode: releaseMode,
|
||||
GrafanaAPIKey: grafanaAPIKey,
|
||||
WhatsNewURL: whatsNewURL,
|
||||
ReleaseNotesURL: releaseNotesURL,
|
||||
DryRun: dryRun,
|
||||
TTL: c.String("ttl"),
|
||||
SimulateRelease: simulateRelease,
|
||||
}
|
||||
|
||||
if err := publishPackages(cfg); err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
|
||||
log.Println("Successfully published packages to grafana.com!")
|
||||
return nil
|
||||
}
|
||||
|
||||
type grafanaConf struct {
|
||||
WhatsNewURL string `json:"whatsNewUrl"`
|
||||
ReleaseNotesURL string `json:"releaseNotesUrl"`
|
||||
}
|
||||
|
||||
type packageConf struct {
|
||||
Grafana grafanaConf `json:"grafana"`
|
||||
}
|
||||
|
||||
func getPackageJSON() (*packageConf, error) {
|
||||
pkgB, err := os.ReadFile("package.json")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read package.json: %w", err)
|
||||
}
|
||||
|
||||
var pconf packageConf
|
||||
if err := json.Unmarshal(pkgB, &pconf); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode package.json: %w", err)
|
||||
}
|
||||
|
||||
return &pconf, nil
|
||||
}
|
||||
|
||||
func getReleaseURLs(semver versions.Semver, pconf *packageConf) (string, string, error) {
|
||||
u := fmt.Sprintf(pconf.Grafana.WhatsNewURL, semver.Major, semver.Minor, semver.Patch)
|
||||
if _, err := url.ParseRequestURI(u); err != nil {
|
||||
return "", "", fmt.Errorf("grafana.whatsNewUrl is invalid in package.json: %q", pconf.Grafana.WhatsNewURL)
|
||||
}
|
||||
if _, err := url.ParseRequestURI(pconf.Grafana.ReleaseNotesURL); err != nil {
|
||||
return "", "", fmt.Errorf("grafana.releaseNotesUrl is invalid in package.json: %q",
|
||||
pconf.Grafana.ReleaseNotesURL)
|
||||
}
|
||||
|
||||
return u, pconf.Grafana.ReleaseNotesURL, nil
|
||||
}
|
||||
|
||||
func Builds(baseURL *url.URL, grafana, version string, packages []packaging.BuildArtifact) ([]GCOMPackage, error) {
|
||||
builds := make([]GCOMPackage, len(packages))
|
||||
for i, v := range packages {
|
||||
var (
|
||||
os = v.Distro
|
||||
arch = v.Arch
|
||||
)
|
||||
|
||||
if v.Distro == "windows" {
|
||||
os = "win"
|
||||
if v.Ext == "msi" {
|
||||
os = "win-installer"
|
||||
}
|
||||
}
|
||||
|
||||
if v.Distro == "rhel" {
|
||||
if arch == "aarch64" {
|
||||
arch = "arm64"
|
||||
}
|
||||
if arch == "x86_64" {
|
||||
arch = "amd64"
|
||||
}
|
||||
}
|
||||
|
||||
if v.Distro == "deb" {
|
||||
if arch == "armhf" {
|
||||
arch = "armv7"
|
||||
if v.RaspberryPi {
|
||||
log.Println(v.Distro, arch, "raspberrypi == true")
|
||||
arch = "armv6"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u := gcom.GetURL(baseURL, version, grafana, v.Distro, v.Arch, v.Ext, v.Musl, v.RaspberryPi)
|
||||
builds[i] = GCOMPackage{
|
||||
OS: os,
|
||||
URL: u.String(),
|
||||
Arch: arch,
|
||||
}
|
||||
}
|
||||
|
||||
return builds, nil
|
||||
}
|
||||
|
||||
// publishPackages publishes packages to grafana.com.
|
||||
func publishPackages(cfg packaging.PublishConfig) error {
|
||||
log.Printf("Publishing Grafana packages, version %s, %s edition, %s mode, dryRun: %v, simulating: %v...\n",
|
||||
cfg.Version, cfg.Edition, cfg.ReleaseMode.Mode, cfg.DryRun, cfg.SimulateRelease)
|
||||
|
||||
versionStr := fmt.Sprintf("v%s", cfg.Version)
|
||||
log.Printf("Creating release %s at grafana.com...\n", versionStr)
|
||||
|
||||
var (
|
||||
pth string
|
||||
grafana = "grafana"
|
||||
)
|
||||
|
||||
switch cfg.Edition {
|
||||
case config.EditionOSS:
|
||||
pth = "oss"
|
||||
case config.EditionEnterprise:
|
||||
grafana = "grafana-enterprise"
|
||||
pth = "enterprise"
|
||||
default:
|
||||
return fmt.Errorf("unrecognized edition %q", cfg.Edition)
|
||||
}
|
||||
|
||||
switch cfg.ReleaseMode.Mode {
|
||||
case config.MainMode, config.DownstreamMode, config.CronjobMode:
|
||||
pth = path.Join(pth, packaging.MainFolder)
|
||||
default:
|
||||
pth = path.Join(pth, packaging.ReleaseFolder)
|
||||
}
|
||||
|
||||
pth = path.Join(pth)
|
||||
baseArchiveURL := &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "dl.grafana.com",
|
||||
Path: pth,
|
||||
}
|
||||
|
||||
builds, err := Builds(baseArchiveURL, grafana, cfg.Version, packaging.ArtifactConfigs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r := Release{
|
||||
Version: cfg.Version,
|
||||
ReleaseDate: time.Now().UTC(),
|
||||
Builds: builds,
|
||||
Stable: cfg.ReleaseMode.Mode == config.TagMode && !cfg.ReleaseMode.IsPreview && !cfg.ReleaseMode.IsTest,
|
||||
Beta: cfg.ReleaseMode.IsPreview,
|
||||
Nightly: cfg.ReleaseMode.Mode == config.CronjobMode,
|
||||
}
|
||||
if cfg.ReleaseMode.Mode == config.TagMode || r.Beta {
|
||||
r.WhatsNewURL = cfg.WhatsNewURL
|
||||
r.ReleaseNotesURL = cfg.ReleaseNotesURL
|
||||
}
|
||||
|
||||
if err := postRequest(cfg, "versions", r, fmt.Sprintf("create release %s", r.Version)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := postRequest(cfg, fmt.Sprintf("versions/%s", cfg.Version), r,
|
||||
fmt.Sprintf("update release %s", cfg.Version)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i, v := range r.Builds {
|
||||
sha, err := getSHA256(v.URL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Builds[i].SHA256 = string(sha)
|
||||
}
|
||||
|
||||
for _, b := range r.Builds {
|
||||
if err := postRequest(cfg, fmt.Sprintf("versions/%s/packages", cfg.Version), b,
|
||||
fmt.Sprintf("create build %s %s", b.OS, b.Arch)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := postRequest(cfg, fmt.Sprintf("versions/%s/packages/%s/%s", cfg.Version, b.Arch, b.OS), b,
|
||||
fmt.Sprintf("update build %s %s", b.OS, b.Arch)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSHA256(u string) ([]byte, error) {
|
||||
shaURL := fmt.Sprintf("%s.sha256", u)
|
||||
|
||||
// nolint:gosec
|
||||
resp, err := http.Get(shaURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err := resp.Body.Close(); err != nil {
|
||||
log.Println("failed to close response body, err: %w", err)
|
||||
}
|
||||
}()
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return nil, fmt.Errorf("failed downloading %s: %s", u, resp.Status)
|
||||
}
|
||||
|
||||
sha256, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sha256, nil
|
||||
}
|
||||
|
||||
func postRequest(cfg packaging.PublishConfig, pth string, body any, descr string) error {
|
||||
var sfx string
|
||||
switch cfg.Edition {
|
||||
case config.EditionOSS:
|
||||
case config.EditionEnterprise:
|
||||
sfx = packaging.EnterpriseSfx
|
||||
default:
|
||||
return fmt.Errorf("unrecognized edition %q", cfg.Edition)
|
||||
}
|
||||
product := fmt.Sprintf("grafana%s", sfx)
|
||||
|
||||
jsonB, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to JSON encode release: %w", err)
|
||||
}
|
||||
|
||||
u, err := constructURL(product, pth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequest(http.MethodPost, u, bytes.NewReader(jsonB))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", cfg.GrafanaAPIKey))
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
log.Printf("Posting to grafana.com API, %s - JSON: %s\n", u, string(jsonB))
|
||||
if cfg.SimulateRelease {
|
||||
log.Println("Only simulating request")
|
||||
return nil
|
||||
}
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed posting to %s (%s): %s", u, descr, err)
|
||||
}
|
||||
defer func() {
|
||||
if err := resp.Body.Close(); err != nil {
|
||||
log.Println("failed to close response body, err: %w", err)
|
||||
}
|
||||
}()
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if strings.Contains(string(body), "already exists") || strings.Contains(string(body), "Nothing to update") {
|
||||
log.Printf("Already exists: %s\n", descr)
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed posting to %s (%s): %s", u, descr, resp.Status)
|
||||
}
|
||||
|
||||
log.Printf("Successfully posted to grafana.com API, %s\n", u)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func constructURL(product string, pth string) (string, error) {
|
||||
productPath := filepath.Clean(filepath.Join("/", product, pth))
|
||||
u, err := url.Parse(grafanaAPI)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
u.Path = path.Join(u.Path, productPath)
|
||||
return u.String(), err
|
||||
}
|
||||
|
||||
type GCOMPackage struct {
|
||||
OS string `json:"os"`
|
||||
URL string `json:"url"`
|
||||
SHA256 string `json:"sha256"`
|
||||
Arch string `json:"arch"`
|
||||
}
|
||||
|
||||
type Release struct {
|
||||
Version string `json:"version"`
|
||||
ReleaseDate time.Time `json:"releaseDate"`
|
||||
Stable bool `json:"stable"`
|
||||
Beta bool `json:"beta"`
|
||||
Nightly bool `json:"nightly"`
|
||||
WhatsNewURL string `json:"whatsNewUrl"`
|
||||
ReleaseNotesURL string `json:"releaseNotesUrl"`
|
||||
Builds []GCOMPackage `json:"-"`
|
||||
}
|
|
@ -1,284 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/packaging"
|
||||
"github.com/grafana/grafana/pkg/build/versions"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_constructURL(t *testing.T) {
|
||||
type args struct {
|
||||
product string
|
||||
pth string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{name: "cleans .. sequence", args: args{"..", ".."}, want: "https://grafana.com/api", wantErr: false},
|
||||
{name: "doesn't clean anything - non malicious url", args: args{"foo", "bar"}, want: "https://grafana.com/api/foo/bar", wantErr: false},
|
||||
{name: "doesn't clean anything - three dots", args: args{"...", "..."}, want: "https://grafana.com/api/.../...", wantErr: false},
|
||||
{name: "cleans .", args: args{"..", ".."}, want: "https://grafana.com/api", wantErr: false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := constructURL(tt.args.product, tt.args.pth)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("constructURL() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("constructURL() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilds(t *testing.T) {
|
||||
baseURL := &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "dl.example.com",
|
||||
Path: path.Join("oss", "release"),
|
||||
}
|
||||
|
||||
version := "1.2.3"
|
||||
grafana := "grafana"
|
||||
packages := []packaging.BuildArtifact{
|
||||
{
|
||||
Distro: "deb",
|
||||
Arch: "arm64",
|
||||
Ext: "deb",
|
||||
},
|
||||
{
|
||||
Distro: "rhel",
|
||||
Arch: "aarch64",
|
||||
Ext: "rpm",
|
||||
},
|
||||
{
|
||||
Distro: "linux",
|
||||
Arch: "arm64",
|
||||
Ext: "tar.gz",
|
||||
},
|
||||
{
|
||||
Distro: "deb",
|
||||
Arch: "armhf",
|
||||
Ext: "deb",
|
||||
RaspberryPi: true,
|
||||
},
|
||||
{
|
||||
Distro: "deb",
|
||||
Arch: "armhf",
|
||||
Ext: "deb",
|
||||
},
|
||||
{
|
||||
Distro: "linux",
|
||||
Arch: "armv7",
|
||||
Ext: "tar.gz",
|
||||
},
|
||||
{
|
||||
Distro: "windows",
|
||||
Arch: "amd64",
|
||||
Ext: "zip",
|
||||
},
|
||||
{
|
||||
Distro: "windows",
|
||||
Arch: "amd64",
|
||||
Ext: "msi",
|
||||
},
|
||||
}
|
||||
|
||||
expect := []GCOMPackage{
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana_1.2.3_arm64.deb",
|
||||
OS: "deb",
|
||||
Arch: "arm64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3-1.aarch64.rpm",
|
||||
OS: "rhel",
|
||||
Arch: "arm64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3.linux-arm64.tar.gz",
|
||||
OS: "linux",
|
||||
Arch: "arm64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-rpi_1.2.3_armhf.deb",
|
||||
OS: "deb",
|
||||
Arch: "armv6",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana_1.2.3_armhf.deb",
|
||||
OS: "deb",
|
||||
Arch: "armv7",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3.linux-armv7.tar.gz",
|
||||
OS: "linux",
|
||||
Arch: "armv7",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3.windows-amd64.zip",
|
||||
OS: "win",
|
||||
Arch: "amd64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3.windows-amd64.msi",
|
||||
OS: "win-installer",
|
||||
Arch: "amd64",
|
||||
},
|
||||
}
|
||||
|
||||
builds, err := Builds(baseURL, grafana, version, packages)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(expect), len(builds))
|
||||
|
||||
for i := range builds {
|
||||
t.Run(fmt.Sprintf("[%d/%d] %s", i+1, len(builds), expect[i].URL), func(t *testing.T) {
|
||||
assert.Equal(t, expect[i].URL, builds[i].URL)
|
||||
assert.Equal(t, expect[i].OS, builds[i].OS)
|
||||
assert.Equal(t, expect[i].Arch, builds[i].Arch)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildsWithPlus(t *testing.T) {
|
||||
baseURL := &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "dl.example.com",
|
||||
Path: path.Join("oss", "release"),
|
||||
}
|
||||
|
||||
version := "1.2.3+example-01"
|
||||
grafana := "grafana"
|
||||
packages := []packaging.BuildArtifact{
|
||||
{
|
||||
Distro: "deb",
|
||||
Arch: "arm64",
|
||||
Ext: "deb",
|
||||
},
|
||||
{
|
||||
Distro: "rhel",
|
||||
Arch: "aarch64",
|
||||
Ext: "rpm",
|
||||
},
|
||||
{
|
||||
Distro: "linux",
|
||||
Arch: "arm64",
|
||||
Ext: "tar.gz",
|
||||
},
|
||||
{
|
||||
Distro: "deb",
|
||||
Arch: "armhf",
|
||||
Ext: "deb",
|
||||
RaspberryPi: true,
|
||||
},
|
||||
{
|
||||
Distro: "deb",
|
||||
Arch: "armhf",
|
||||
Ext: "deb",
|
||||
},
|
||||
{
|
||||
Distro: "linux",
|
||||
Arch: "armv7",
|
||||
Ext: "tar.gz",
|
||||
},
|
||||
{
|
||||
Distro: "windows",
|
||||
Arch: "amd64",
|
||||
Ext: "zip",
|
||||
},
|
||||
{
|
||||
Distro: "windows",
|
||||
Arch: "amd64",
|
||||
Ext: "msi",
|
||||
},
|
||||
}
|
||||
|
||||
expect := []GCOMPackage{
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana_1.2.3+example~01_arm64.deb",
|
||||
OS: "deb",
|
||||
Arch: "arm64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3+example~01-1.aarch64.rpm",
|
||||
OS: "rhel",
|
||||
Arch: "arm64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3+example-01.linux-arm64.tar.gz",
|
||||
OS: "linux",
|
||||
Arch: "arm64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-rpi_1.2.3+example~01_armhf.deb",
|
||||
OS: "deb",
|
||||
Arch: "armv6",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana_1.2.3+example~01_armhf.deb",
|
||||
OS: "deb",
|
||||
Arch: "armv7",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3+example-01.linux-armv7.tar.gz",
|
||||
OS: "linux",
|
||||
Arch: "armv7",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3+example-01.windows-amd64.zip",
|
||||
OS: "win",
|
||||
Arch: "amd64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3+example-01.windows-amd64.msi",
|
||||
OS: "win-installer",
|
||||
Arch: "amd64",
|
||||
},
|
||||
}
|
||||
|
||||
builds, err := Builds(baseURL, grafana, version, packages)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(expect), len(builds))
|
||||
|
||||
for i := range builds {
|
||||
t.Run(fmt.Sprintf("[%d/%d] %s", i+1, len(builds), expect[i].URL), func(t *testing.T) {
|
||||
assert.Equal(t, expect[i].URL, builds[i].URL)
|
||||
assert.Equal(t, expect[i].OS, builds[i].OS)
|
||||
assert.Equal(t, expect[i].Arch, builds[i].Arch)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReleaseURLs(t *testing.T) {
|
||||
f := "https://grafana.com/whats-new-in-v%[1]s-%[2]s"
|
||||
|
||||
smv := versions.Semver{
|
||||
Major: "1",
|
||||
Minor: "2",
|
||||
Patch: "3",
|
||||
}
|
||||
|
||||
conf := packageConf{
|
||||
Grafana: grafanaConf{
|
||||
WhatsNewURL: f,
|
||||
ReleaseNotesURL: "https://example.com",
|
||||
},
|
||||
}
|
||||
|
||||
expect := "https://grafana.com/whats-new-in-v1-2"
|
||||
|
||||
a, _, err := getReleaseURLs(smv, &conf)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expect, a)
|
||||
}
|
|
@ -4,18 +4,9 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/cmd/util"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/cmd"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var additionalCommands []*cli.Command = make([]*cli.Command, 0, 5)
|
||||
|
||||
//nolint:unused
|
||||
func registerAppCommand(c *cli.Command) {
|
||||
additionalCommands = append(additionalCommands, c)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// TODO change the registerer if the user is running using a JSON file etc
|
||||
for k, v := range cmd.Artifacts {
|
||||
|
@ -25,272 +16,6 @@ func main() {
|
|||
}
|
||||
|
||||
app := cmd.GlobalCLI.App()
|
||||
artifactsCommand := cmd.GlobalCLI.ArtifactsCommand()
|
||||
artifactsCommand.Subcommands = cli.Commands{
|
||||
{
|
||||
Name: "storybook",
|
||||
Usage: "[ARCHIVED] 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: "[ARCHIVED] 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: "[ARCHIVED] 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: "[ARCHIVED] Handle Grafana Docker images",
|
||||
Subcommands: cli.Commands{
|
||||
{
|
||||
Name: "fetch",
|
||||
Usage: "Fetch Grafana Docker images",
|
||||
ArgsUsage: "[version]",
|
||||
Action: util.MaxArgCountWrapper(1, FetchImages),
|
||||
Flags: []cli.Flag{
|
||||
&editionFlag,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "npm",
|
||||
Usage: "[ARCHIVED] 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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
app.Commands = append(app.Commands, []*cli.Command{
|
||||
{
|
||||
Name: "e2e-tests",
|
||||
Usage: "[ARCHIVED] Run Grafana e2e tests",
|
||||
Action: EndToEndTests,
|
||||
Flags: []cli.Flag{
|
||||
&triesFlag,
|
||||
&cli.IntFlag{
|
||||
Name: "port",
|
||||
Value: 3001,
|
||||
Usage: "Specify the server port",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "suite",
|
||||
Usage: "Specify the end-to-end tests suite to be used",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "host",
|
||||
Value: "grafana-server",
|
||||
Usage: "Specify the server host",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "video",
|
||||
Value: "true",
|
||||
Usage: "Specify if videos should be recorded",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "upload-cdn",
|
||||
Usage: "[ARCHIVED] Upload public/* to a cdn bucket",
|
||||
Action: UploadCDN,
|
||||
Flags: []cli.Flag{
|
||||
&editionFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "publish-metrics",
|
||||
Usage: "[ARCHIVED] Publish a set of metrics from stdin",
|
||||
ArgsUsage: "<api-key>",
|
||||
Action: util.MaxArgCountWrapper(1, PublishMetrics),
|
||||
},
|
||||
{
|
||||
Name: "verify-drone",
|
||||
Usage: "[ARCHIVED] Verify Drone configuration",
|
||||
Action: VerifyDrone,
|
||||
},
|
||||
{
|
||||
Name: "store-storybook",
|
||||
Usage: "[ARCHIVED] Stores storybook to GCS buckets",
|
||||
Action: StoreStorybook,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "deployment",
|
||||
Usage: "Kind of deployment (e.g. canary/latest)",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "verify-storybook",
|
||||
Usage: "[ARCHIVED] Integrity check for storybook build",
|
||||
Action: VerifyStorybook,
|
||||
},
|
||||
{
|
||||
Name: "upload-packages",
|
||||
Usage: "[ARCHIVED] Upload Grafana packages",
|
||||
Action: UploadPackages,
|
||||
Flags: []cli.Flag{
|
||||
&jobsFlag,
|
||||
&editionFlag,
|
||||
&cli.BoolFlag{
|
||||
Name: "enterprise2",
|
||||
Usage: "Declare if the edition is enterprise2",
|
||||
},
|
||||
},
|
||||
},
|
||||
artifactsCommand,
|
||||
{
|
||||
Name: "publish",
|
||||
Usage: "[ARCHIVED] Publish packages to Grafana com and repositories",
|
||||
Subcommands: cli.Commands{
|
||||
{
|
||||
Name: "grafana-com",
|
||||
Usage: "Publish packages to grafana.com",
|
||||
Action: GrafanaCom,
|
||||
Flags: []cli.Flag{
|
||||
&editionFlag,
|
||||
&buildIDFlag,
|
||||
&util.DryRunFlag,
|
||||
&cli.StringFlag{
|
||||
Name: "src-bucket",
|
||||
Value: "grafana-downloads",
|
||||
Usage: "Google Cloud Storage bucket",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "github",
|
||||
Usage: "Publish packages to GitHub releases",
|
||||
Action: PublishGithub,
|
||||
Flags: []cli.Flag{
|
||||
&util.DryRunFlag,
|
||||
&cli.StringFlag{
|
||||
Name: "path",
|
||||
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",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "aws",
|
||||
Usage: "Publish image to AWS Marketplace releases",
|
||||
Action: PublishAwsMarketplace,
|
||||
Flags: []cli.Flag{
|
||||
&util.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",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}...)
|
||||
|
||||
app.Commands = append(app.Commands, additionalCommands...)
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatalln(err)
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/npm"
|
||||
)
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
if strings.Contains(tag, "security") {
|
||||
log.Printf("skipping npm publish because version '%s' has 'security'", tag)
|
||||
return nil
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
if strings.Contains(tag, "security") {
|
||||
log.Printf("skipping npm publish because version '%s' has 'security'", tag)
|
||||
return nil
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
if strings.Contains(tag, "security") {
|
||||
log.Printf("skipping npm publish because version '%s' has 'security'", tag)
|
||||
return nil
|
||||
}
|
||||
|
||||
err := npm.PublishNpmPackages(c.Context, tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
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
|
||||
}
|
|
@ -1,310 +0,0 @@
|
|||
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/image"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
)
|
||||
|
||||
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 image.PullOptions) (io.ReadCloser, error)
|
||||
ImageTag(ctx context.Context, source string, target string) error
|
||||
ImagePush(ctx context.Context, image string, options image.PushOptions) (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(registry.AuthConfig{
|
||||
Username: authString[0],
|
||||
Password: authString[1],
|
||||
})
|
||||
s.auth = base64.StdEncoding.EncodeToString(authData)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *AwsMarketplacePublishingService) PullImage(ctx context.Context, img string, version string) error {
|
||||
reader, err := s.docker.ImagePull(ctx, fmt.Sprintf("%s:%s", img, version), image.PullOptions{
|
||||
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), image.PushOptions{
|
||||
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)
|
||||
}
|
|
@ -1,211 +0,0 @@
|
|||
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/image"
|
||||
"github.com/grafana/grafana/pkg/build/cmd/util"
|
||||
"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{
|
||||
&util.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 image.PullOptions) (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 image.PushOptions) (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
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package main
|
||||
|
||||
type publishConfig struct {
|
||||
tag string
|
||||
srcBucket string
|
||||
destBucket string
|
||||
enterprise2DestBucket string
|
||||
enterprise2SecurityPrefix string
|
||||
staticAssetsBucket string
|
||||
staticAssetEditions []string
|
||||
storybookBucket string
|
||||
security bool
|
||||
}
|
|
@ -1,191 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/google/go-github/v70/github"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
|
@ -1,240 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-github/v70/github"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/cmd/util"
|
||||
)
|
||||
|
||||
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{
|
||||
&util.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
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/metrics"
|
||||
)
|
||||
|
||||
func PublishMetrics(c *cli.Context) error {
|
||||
apiKey := c.Args().Get(0)
|
||||
|
||||
input, err := io.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
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.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.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.Exit(fmt.Sprintf("publishing metrics failed: %s", err), 1)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
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
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
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
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
"github.com/grafana/grafana/pkg/build/gcloud/storage"
|
||||
)
|
||||
|
||||
// StoreStorybook implements the sub-command "store-storybook".
|
||||
func StoreStorybook(c *cli.Context) error {
|
||||
deployment := c.String("deployment")
|
||||
|
||||
metadata, err := config.GenerateMetadata(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buildConfig, err := config.GetBuildConfig(metadata.ReleaseMode.Mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
storybookBucket := buildConfig.Buckets.Storybook
|
||||
srcPath := buildConfig.Buckets.StorybookSrcDir
|
||||
srcPath = filepath.Join(srcPath, deployment)
|
||||
|
||||
gcs, err := storage.New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bucket := gcs.Bucket(storybookBucket)
|
||||
|
||||
if err := gcs.DeleteDir(c.Context, bucket, srcPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("Successfully cleaned source: %s/%s\n", storybookBucket, srcPath)
|
||||
|
||||
if err := gcs.CopyLocalDir(c.Context, "packages/grafana-ui/dist/storybook", bucket, srcPath, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("Successfully stored storybook to: %s/%s!\n", storybookBucket, srcPath)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
"github.com/grafana/grafana/pkg/build/gcloud/storage"
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
|
@ -1,234 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
"github.com/grafana/grafana/pkg/build/droneutil"
|
||||
"github.com/grafana/grafana/pkg/build/gcloud"
|
||||
)
|
||||
|
||||
// PackageRegexp returns a regexp for matching packages corresponding to a certain Grafana edition.
|
||||
func PackageRegexp(edition config.Edition) *regexp.Regexp {
|
||||
var sfx string
|
||||
switch edition {
|
||||
case config.EditionOSS:
|
||||
case config.EditionEnterprise:
|
||||
sfx = "-enterprise"
|
||||
case config.EditionEnterprise2:
|
||||
sfx = "-enterprise2"
|
||||
default:
|
||||
panic(fmt.Sprintf("unrecognized edition %q", edition))
|
||||
}
|
||||
rePkg, err := regexp.Compile(fmt.Sprintf(`^grafana%s(?:-rpi)?[-_][^-_]+.*$`, sfx))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to compile regexp: %s", err))
|
||||
}
|
||||
|
||||
return rePkg
|
||||
}
|
||||
|
||||
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 := 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
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
)
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/drone/drone-cli/drone/lint"
|
||||
"github.com/drone/drone-cli/drone/starlark"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
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 {
|
||||
const yml = ".drone.yml"
|
||||
const backup = ".drone.yml.bak"
|
||||
|
||||
if err := fsutil.CopyFile(yml, backup); err != nil {
|
||||
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 {
|
||||
log.Printf("Failed to rename %s to %s", backup, yml)
|
||||
}
|
||||
if err := os.Rename(backup, yml); err != nil {
|
||||
log.Printf("Failed to rename %s to %s", backup, yml)
|
||||
}
|
||||
}()
|
||||
|
||||
flags := &flag.FlagSet{}
|
||||
for _, flag := range starlark.Command.Flags {
|
||||
flag.Apply(flags)
|
||||
}
|
||||
if err := flags.Set("format", "true"); err != nil {
|
||||
return err
|
||||
}
|
||||
cStarlark := cliv1.NewContext(cliv1.NewApp(), flags, nil)
|
||||
action := starlark.Command.Action.(func(*cliv1.Context))
|
||||
action(cStarlark)
|
||||
|
||||
if err := verifyYAML(yml, backup); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
flags = &flag.FlagSet{}
|
||||
for _, flag := range lint.Command.Flags {
|
||||
flag.Apply(flags)
|
||||
}
|
||||
err := flags.Set("trusted", "true")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cLint := cliv1.NewContext(cliv1.NewApp(), flags, nil)
|
||||
actionE := lint.Command.Action.(func(*cliv1.Context) error)
|
||||
if err := actionE(cLint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("%s is valid", yml)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readConfig(fpath string) ([]map[string]any, error) {
|
||||
//nolint:gosec
|
||||
f, err := os.Open(fpath)
|
||||
if err != nil {
|
||||
return nil, cli.Exit(fmt.Sprintf("failed to read %s: %s", fpath, err), 1)
|
||||
}
|
||||
defer func() {
|
||||
if err := f.Close(); err != nil {
|
||||
log.Println("error closing file", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// The YAML stream may contain multiple pipeline configurations, read them all
|
||||
dec := yaml.NewDecoder(f)
|
||||
var c []map[string]any
|
||||
for {
|
||||
var m map[string]any
|
||||
if err := dec.Decode(&m); err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
return nil, cli.Exit(fmt.Sprintf("Failed to decode %s: %s", fpath, err), 1)
|
||||
}
|
||||
|
||||
if m["kind"] == "signature" {
|
||||
log.Printf("Ignoring a signature")
|
||||
continue
|
||||
}
|
||||
|
||||
c = append(c, m)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func verifyYAML(yml, backup string) error {
|
||||
log.Printf("Comparing %s and %s", yml, backup)
|
||||
|
||||
c1, err := readConfig(yml)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c2, err := readConfig(backup)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !cmp.Equal(c1, c2) {
|
||||
return cli.Exit(fmt.Sprintf("%s is out of sync with .drone.star - regenerate it with drone starlark convert",
|
||||
yml), 1)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
// Package verifystorybook contains the sub-command "verify-storybook".
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/fsutil"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// 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 := fsutil.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
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package config
|
||||
|
||||
type Config struct {
|
||||
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
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package config
|
||||
|
||||
type Edition string
|
||||
|
||||
const (
|
||||
EditionOSS Edition = "oss"
|
||||
EditionEnterprise Edition = "enterprise"
|
||||
EditionEnterprise2 Edition = "enterprise2"
|
||||
)
|
|
@ -1,103 +0,0 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/droneutil"
|
||||
)
|
||||
|
||||
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 := GenerateGrafanaVersion(buildID, ".")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return version, nil
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
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-12345"
|
||||
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, IsPreview: false, IsTest: false}},
|
||||
{map[string]string{DroneBuildEvent: Tag, DroneTargetBranch: "", DroneTag: "v9.2.0-preview", DroneSemverPrerelease: "preview", DroneBuildNumber: "12345"}, "9.2.0-preview", ReleaseMode{Mode: TagMode, IsPreview: 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, IsPreview: false, IsTest: true}},
|
||||
{map[string]string{DroneBuildEvent: Promote, DroneTargetBranch: "", DroneTag: "v9.2.0", DroneSemverPrerelease: "", DroneBuildNumber: "12345"}, "9.2.0", ReleaseMode{Mode: TagMode, IsPreview: false, IsTest: false}},
|
||||
{map[string]string{DroneBuildEvent: Promote, DroneTargetBranch: "", DroneTag: "v9.2.0-preview", DroneSemverPrerelease: "preview", DroneBuildNumber: "12345"}, "9.2.0-preview", ReleaseMode{Mode: TagMode, IsPreview: 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, IsPreview: 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()
|
||||
t.Setenv("DRONE_COMMIT", "abcd12345")
|
||||
for k, v := range envMap {
|
||||
t.Setenv(k, v)
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"version": "9.2.0-pre"
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
package config
|
||||
|
||||
// Variant is the OS / Architecture combination that Grafana can be compiled for.
|
||||
type Variant string
|
||||
|
||||
const (
|
||||
VariantLinuxAmd64 Variant = "linux-amd64"
|
||||
VariantLinuxAmd64Musl Variant = "linux-amd64-musl"
|
||||
VariantArmV6 Variant = "linux-armv6"
|
||||
VariantArmV7 Variant = "linux-armv7"
|
||||
VariantArmV7Musl Variant = "linux-armv7-musl"
|
||||
VariantArm64 Variant = "linux-arm64"
|
||||
VariantArm64Musl Variant = "linux-arm64-musl"
|
||||
VariantDarwinAmd64 Variant = "darwin-amd64"
|
||||
VariantWindowsAmd64 Variant = "windows-amd64"
|
||||
)
|
||||
|
||||
var AllVariants = []Variant{
|
||||
// https://github.com/golang/go/issues/58425 disabling arm builds until go issue is resolved
|
||||
// VariantArmV6,
|
||||
// VariantArmV7,
|
||||
// VariantArmV7Musl,
|
||||
VariantArm64,
|
||||
VariantArm64Musl,
|
||||
VariantDarwinAmd64,
|
||||
VariantWindowsAmd64,
|
||||
VariantLinuxAmd64,
|
||||
VariantLinuxAmd64Musl,
|
||||
}
|
||||
|
||||
// Architecture is an allowed value in the GOARCH environment variable.
|
||||
type Architecture string
|
||||
|
||||
const (
|
||||
ArchAMD64 Architecture = "amd64"
|
||||
ArchARMv6 Architecture = "armv6"
|
||||
ArchARMv7 Architecture = "armv7"
|
||||
ArchARM64 Architecture = "arm64"
|
||||
ArchARMHF Architecture = "armhf"
|
||||
ArchARMHFP Architecture = "armhfp"
|
||||
ArchARM Architecture = "arm"
|
||||
)
|
||||
|
||||
type OS string
|
||||
|
||||
const (
|
||||
OSWindows OS = "windows"
|
||||
OSDarwin OS = "darwin"
|
||||
OSLinux OS = "linux"
|
||||
)
|
||||
|
||||
type LibC string
|
||||
|
||||
const (
|
||||
LibCMusl = "musl"
|
||||
)
|
||||
|
||||
// Distribution is the base os image where the Grafana image is built on.
|
||||
type Distribution string
|
||||
|
||||
const (
|
||||
Ubuntu Distribution = "ubuntu"
|
||||
Alpine Distribution = "alpine"
|
||||
)
|
|
@ -5,72 +5,9 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/git"
|
||||
)
|
||||
|
||||
type Metadata struct {
|
||||
GrafanaVersion string `json:"version,omitempty"`
|
||||
ReleaseMode ReleaseMode `json:"releaseMode,omitempty"`
|
||||
GrabplVersion string `json:"grabplVersion,omitempty"`
|
||||
CurrentCommit string `json:"currentCommit,omitempty"`
|
||||
}
|
||||
|
||||
type ReleaseMode struct {
|
||||
Mode VersionMode `json:"mode,omitempty"`
|
||||
IsPreview bool `json:"IsPreview,omitempty"`
|
||||
IsTest bool `json:"isTest,omitempty"`
|
||||
}
|
||||
|
||||
type PluginSignature struct {
|
||||
Sign bool `json:"sign,omitempty"`
|
||||
AdminSign bool `json:"adminSign,omitempty"`
|
||||
}
|
||||
|
||||
type Docker struct {
|
||||
ShouldSave bool `json:"shouldSave,omitempty"`
|
||||
Distribution []Distribution `json:"distribution,omitempty"`
|
||||
Architectures []Architecture `json:"archs,omitempty"`
|
||||
PrereleaseBucket string `json:"prereleaseBucket,omitempty"`
|
||||
}
|
||||
|
||||
type Buckets struct {
|
||||
Artifacts string `json:"artifacts,omitempty"`
|
||||
ArtifactsEnterprise2 string `json:"artifactsEnterprise2,omitempty"`
|
||||
CDNAssets string `json:"CDNAssets,omitempty"`
|
||||
CDNAssetsDir string `json:"CDNAssetsDir,omitempty"`
|
||||
Storybook string `json:"storybook,omitempty"`
|
||||
StorybookSrcDir string `json:"storybookSrcDir,omitempty"`
|
||||
}
|
||||
|
||||
// BuildConfig represents the struct that defines all of the different variables used to build Grafana
|
||||
type BuildConfig struct {
|
||||
Variants []Variant `json:"variants,omitempty"`
|
||||
PluginSignature PluginSignature `json:"pluginSignature,omitempty"`
|
||||
Docker Docker `json:"docker,omitempty"`
|
||||
Buckets Buckets `json:"buckets,omitempty"`
|
||||
}
|
||||
|
||||
func (md *Metadata) GetReleaseMode() (ReleaseMode, error) {
|
||||
return md.ReleaseMode, nil
|
||||
}
|
||||
|
||||
// VersionMap is a map of versions. Each key of the Versions map is an event that uses the config as the value for that key.
|
||||
// For example, the 'pull_request' key will have data in it that might cause Grafana to be built differently in a pull request,
|
||||
// than the way it will be built in 'main'
|
||||
type VersionMap map[VersionMode]BuildConfig
|
||||
|
||||
// GetBuildConfig reads the embedded config.json and decodes it.
|
||||
func GetBuildConfig(mode VersionMode) (*BuildConfig, error) {
|
||||
if v, ok := Versions[mode]; ok {
|
||||
return &v, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("mode '%s' not found in version list", mode)
|
||||
}
|
||||
|
||||
// GenerateGrafanaVersion gets the Grafana version from the package.json
|
||||
func GenerateGrafanaVersion(buildID, grafanaDir string) (string, error) {
|
||||
version, err := GetPackageJSONVersion(grafanaDir)
|
||||
|
@ -106,55 +43,6 @@ func GetPackageJSONVersion(grafanaDir string) (string, error) {
|
|||
return version, nil
|
||||
}
|
||||
|
||||
func CheckDroneTargetBranch() (VersionMode, error) {
|
||||
rePRCheckBranch := git.PRCheckRegexp()
|
||||
reRlsBranch := regexp.MustCompile(`^v\d+\.\d+\.x$`)
|
||||
target := os.Getenv("DRONE_TARGET_BRANCH")
|
||||
if target == "" {
|
||||
return "", fmt.Errorf("failed to get DRONE_TARGET_BRANCH environmental variable")
|
||||
} else if target == string(MainMode) {
|
||||
return MainMode, nil
|
||||
}
|
||||
if reRlsBranch.MatchString(target) {
|
||||
return ReleaseBranchMode, nil
|
||||
}
|
||||
if rePRCheckBranch.MatchString(target) {
|
||||
return PullRequestMode, nil
|
||||
}
|
||||
fmt.Printf("unrecognized target branch: %s, defaulting to %s\n", target, PullRequestMode)
|
||||
return PullRequestMode, nil
|
||||
}
|
||||
|
||||
func CheckSemverSuffix() (ReleaseMode, error) {
|
||||
rePreviewRls := regexp.MustCompile(`preview.*`)
|
||||
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...")
|
||||
return ReleaseMode{Mode: TagMode}, nil
|
||||
}
|
||||
switch {
|
||||
case rePreviewRls.MatchString(tagSuffix):
|
||||
return ReleaseMode{Mode: TagMode, IsPreview: 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
|
||||
}
|
||||
}
|
||||
|
||||
func GetDroneCommit() (string, error) {
|
||||
commit := strings.TrimSpace(os.Getenv("DRONE_COMMIT"))
|
||||
if commit == "" {
|
||||
return "", fmt.Errorf("the environment variable DRONE_COMMIT is missing")
|
||||
}
|
||||
return commit, nil
|
||||
}
|
||||
|
||||
func shortenBuildID(buildID string) string {
|
||||
buildID = strings.ReplaceAll(buildID, "-", "")
|
||||
if len(buildID) < 9 {
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
package config
|
||||
|
||||
// VersionMode defines the source event that created a release or published version
|
||||
type VersionMode string
|
||||
|
||||
const (
|
||||
MainMode VersionMode = "main"
|
||||
TagMode VersionMode = "release"
|
||||
ReleaseBranchMode VersionMode = "branch"
|
||||
PullRequestMode VersionMode = "pull_request"
|
||||
DownstreamMode VersionMode = "downstream"
|
||||
Enterprise2Mode VersionMode = "enterprise2"
|
||||
CronjobMode VersionMode = "cron"
|
||||
CloudMode VersionMode = "cloud"
|
||||
)
|
||||
|
||||
const (
|
||||
Tag = "tag"
|
||||
PullRequest = "pull_request"
|
||||
Push = "push"
|
||||
Custom = "custom"
|
||||
Promote = "promote"
|
||||
Cronjob = "cron"
|
||||
)
|
||||
|
||||
const (
|
||||
MainBranch = "main"
|
||||
)
|
|
@ -1,237 +0,0 @@
|
|||
package config
|
||||
|
||||
var Versions = VersionMap{
|
||||
PullRequestMode: {
|
||||
Variants: []Variant{
|
||||
VariantLinuxAmd64,
|
||||
VariantLinuxAmd64Musl,
|
||||
VariantDarwinAmd64,
|
||||
VariantWindowsAmd64,
|
||||
VariantArm64,
|
||||
VariantArm64Musl,
|
||||
},
|
||||
PluginSignature: PluginSignature{
|
||||
Sign: false,
|
||||
AdminSign: false,
|
||||
},
|
||||
Docker: Docker{
|
||||
ShouldSave: false,
|
||||
Architectures: []Architecture{
|
||||
ArchAMD64,
|
||||
ArchARM64,
|
||||
},
|
||||
Distribution: []Distribution{
|
||||
Alpine,
|
||||
},
|
||||
},
|
||||
},
|
||||
MainMode: {
|
||||
Variants: []Variant{
|
||||
VariantArmV6,
|
||||
VariantArmV7,
|
||||
VariantArmV7Musl,
|
||||
VariantArm64,
|
||||
VariantArm64Musl,
|
||||
VariantDarwinAmd64,
|
||||
VariantWindowsAmd64,
|
||||
VariantLinuxAmd64,
|
||||
VariantLinuxAmd64Musl,
|
||||
},
|
||||
PluginSignature: PluginSignature{
|
||||
Sign: true,
|
||||
AdminSign: true,
|
||||
},
|
||||
Docker: Docker{
|
||||
ShouldSave: false,
|
||||
Architectures: []Architecture{
|
||||
ArchAMD64,
|
||||
ArchARM64,
|
||||
ArchARMv7, // GOARCH=ARM is used for both armv6 and armv7. They are differentiated by the GOARM variable.
|
||||
},
|
||||
Distribution: []Distribution{
|
||||
Alpine,
|
||||
Ubuntu,
|
||||
},
|
||||
},
|
||||
Buckets: Buckets{
|
||||
Artifacts: "grafana-downloads",
|
||||
ArtifactsEnterprise2: "grafana-downloads-enterprise2",
|
||||
CDNAssets: "grafana-static-assets",
|
||||
Storybook: "grafana-storybook",
|
||||
},
|
||||
},
|
||||
DownstreamMode: {
|
||||
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, // GOARCH=ARM is used for both armv6 and armv7. They are differentiated by the GOARM variable.
|
||||
},
|
||||
Distribution: []Distribution{
|
||||
Alpine,
|
||||
Ubuntu,
|
||||
},
|
||||
},
|
||||
Buckets: Buckets{
|
||||
Artifacts: "grafana-downloads",
|
||||
ArtifactsEnterprise2: "grafana-downloads-enterprise2",
|
||||
CDNAssets: "grafana-static-assets",
|
||||
},
|
||||
},
|
||||
ReleaseBranchMode: {
|
||||
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-downloads",
|
||||
ArtifactsEnterprise2: "grafana-downloads-enterprise2",
|
||||
CDNAssets: "grafana-static-assets",
|
||||
},
|
||||
},
|
||||
TagMode: {
|
||||
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",
|
||||
},
|
||||
},
|
||||
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",
|
||||
},
|
||||
},
|
||||
}
|
|
@ -26,27 +26,7 @@ func (c *CLI) App() *cli.App {
|
|||
Name: "grafana-build",
|
||||
Usage: "A build tool for Grafana",
|
||||
Commands: []*cli.Command{
|
||||
// Legacy commands, should eventually be completely replaced by what's in "artifacts"
|
||||
{
|
||||
Name: "package",
|
||||
Subcommands: []*cli.Command{
|
||||
PackagePublishCommand,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "docker",
|
||||
Subcommands: []*cli.Command{
|
||||
DockerPublishCommand,
|
||||
},
|
||||
},
|
||||
ProImageCommand,
|
||||
{
|
||||
Name: "npm",
|
||||
Subcommands: []*cli.Command{
|
||||
PublishNPMCommand,
|
||||
},
|
||||
},
|
||||
GCOMCommand,
|
||||
c.ArtifactsCommand(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/pipelines"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var DockerPublishCommand = &cli.Command{
|
||||
Name: "publish",
|
||||
Action: PipelineActionWithPackageInput(pipelines.PublishDocker),
|
||||
Usage: "Using a grafana.docker.tar.gz as input (ideally one built using the 'package' command), publish a docker image and manifest",
|
||||
Flags: JoinFlagsWithDefault(
|
||||
PackageInputFlags,
|
||||
DockerFlags,
|
||||
DockerPublishFlags,
|
||||
GCPFlags,
|
||||
ConcurrencyFlags,
|
||||
),
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var GCOMCommand = &cli.Command{
|
||||
Name: "gcom",
|
||||
Description: "Executes requests to grafana.com",
|
||||
Subcommands: []*cli.Command{GCOMPublishCommand},
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/pipelines"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var GCOMPublishCommand = &cli.Command{
|
||||
Name: "publish",
|
||||
Action: PipelineActionWithPackageInput(pipelines.PublishGCOM),
|
||||
Description: "Publishes a grafana.tar.gz (ideally one built using the 'package' command) to grafana.com (--destination will be the download path)",
|
||||
Flags: JoinFlagsWithDefault(
|
||||
GCOMFlags,
|
||||
PackageInputFlags,
|
||||
PublishFlags,
|
||||
ConcurrencyFlags,
|
||||
),
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"dagger.io/dagger"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/pipelines"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// Deprecated: use the Artifact type instead
|
||||
func PipelineActionWithPackageInput(pf pipelines.PipelineFuncWithPackageInput) cli.ActionFunc {
|
||||
return func(c *cli.Context) error {
|
||||
var (
|
||||
ctx = c.Context
|
||||
opts = []dagger.ClientOpt{}
|
||||
)
|
||||
if c.Bool("verbose") {
|
||||
opts = append(opts, dagger.WithLogOutput(os.Stderr))
|
||||
}
|
||||
client, err := dagger.Connect(ctx, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func(c *dagger.Client) {
|
||||
if err := c.Close(); err != nil {
|
||||
fmt.Println("error closing dagger client:", err)
|
||||
}
|
||||
}(client)
|
||||
|
||||
args, err := pipelines.PipelineArgsFromContext(ctx, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(args.PackageInputOpts.Packages) == 0 {
|
||||
return errors.New("expected at least one package from a '--package' flag")
|
||||
}
|
||||
|
||||
if err := pf(ctx, client, args); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/pipelines"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var PublishNPMCommand = &cli.Command{
|
||||
Name: "publish",
|
||||
Action: PipelineActionWithPackageInput(pipelines.PublishNPM),
|
||||
Usage: "Using a grafana.tar.gz as input (ideally one built using the 'package' command), take the npm artifacts and publish them on NPM.",
|
||||
Flags: JoinFlagsWithDefault(
|
||||
PackageInputFlags,
|
||||
NPMFlags,
|
||||
GCPFlags,
|
||||
ConcurrencyFlags,
|
||||
),
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/pipelines"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var PackagePublishCommand = &cli.Command{
|
||||
Name: "publish",
|
||||
Action: PipelineActionWithPackageInput(pipelines.PublishPackage),
|
||||
Description: "Publishes a grafana.tar.gz (ideally one built using the 'package' command) in the destination directory (--destination)",
|
||||
Flags: JoinFlagsWithDefault(
|
||||
PackageInputFlags,
|
||||
PublishFlags,
|
||||
GCPFlags,
|
||||
ConcurrencyFlags,
|
||||
),
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/pipelines"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var ProImageCommand = &cli.Command{
|
||||
Name: "pro-image",
|
||||
Action: PipelineActionWithPackageInput(pipelines.ProImage),
|
||||
Description: "Creates a hosted grafana pro image",
|
||||
Flags: JoinFlagsWithDefault(ProImageFlags, GCPFlags, PackageInputFlags),
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
package containers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"dagger.io/dagger"
|
||||
)
|
||||
|
||||
const GoogleCloudImage = "google/cloud-sdk:alpine"
|
||||
|
||||
// GCPAuthenticator injects authentication information into the provided container.
|
||||
type GCPAuthenticator interface {
|
||||
Authenticate(*dagger.Client, *dagger.Container) (*dagger.Container, error)
|
||||
}
|
||||
|
||||
// GCPServiceAccount satisfies GCPAuthenticator and injects the provided ServiceAccount into the filesystem and adds a 'gcloud auth activate-service-account'
|
||||
type GCPServiceAccount struct {
|
||||
DaggerFile *dagger.File
|
||||
JSONFile string
|
||||
}
|
||||
|
||||
func (a *GCPServiceAccount) Authenticate(d *dagger.Client, c *dagger.Container) (*dagger.Container, error) {
|
||||
if a.DaggerFile == nil && a.JSONFile == "" {
|
||||
return nil, fmt.Errorf("GCPServiceAccount authentication missed JSONFile AND DaggerFile")
|
||||
}
|
||||
var container *dagger.Container
|
||||
|
||||
if a.JSONFile != "" {
|
||||
container = c.WithMountedFile(
|
||||
"/opt/service_account.json",
|
||||
d.Host().Directory(filepath.Dir(a.JSONFile)).File(filepath.Base(a.JSONFile)),
|
||||
)
|
||||
}
|
||||
|
||||
if a.DaggerFile != nil {
|
||||
container = c.WithMountedFile("/opt/service_account.json", a.DaggerFile)
|
||||
}
|
||||
|
||||
return container.WithExec([]string{"gcloud", "auth", "activate-service-account", "--key-file", "/opt/service_account.json"}), nil
|
||||
}
|
||||
|
||||
func NewGCPServiceAccount(filepath string) *GCPServiceAccount {
|
||||
return &GCPServiceAccount{
|
||||
JSONFile: filepath,
|
||||
}
|
||||
}
|
||||
|
||||
func NewGCPServiceAccountWithFile(file *dagger.File) *GCPServiceAccount {
|
||||
return &GCPServiceAccount{
|
||||
DaggerFile: file,
|
||||
}
|
||||
}
|
||||
|
||||
// InheritedServiceAccount uses `gcloud` command in the current shell to get the GCS credentials.
|
||||
// This type should really only be used when running locally.
|
||||
type GCPInheritedAuth struct{}
|
||||
|
||||
func (a *GCPInheritedAuth) Authenticate(d *dagger.Client, c *dagger.Container) (*dagger.Container, error) {
|
||||
if val, ok := os.LookupEnv("GOOGLE_APPLICATION_CREDENTIALS"); ok {
|
||||
return c.WithMountedDirectory("/auth/credentials.json", d.Host().Directory(val)).WithEnvVariable("GOOGLE_APPLICATION_CREDENTIALS", "/auth/credentials.json"), nil
|
||||
}
|
||||
|
||||
cfg, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.WithMountedDirectory("/root/.config/gcloud", d.Host().Directory(filepath.Join(cfg, ".config", "gcloud"))), nil
|
||||
}
|
||||
|
||||
func GCSUploadDirectory(d *dagger.Client, image string, auth GCPAuthenticator, dir *dagger.Directory, dst string) (*dagger.Container, error) {
|
||||
container := d.Container().From(image).
|
||||
WithMountedDirectory("/src", dir)
|
||||
|
||||
var err error
|
||||
container, err = auth.Authenticate(d, container)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
secret := d.SetSecret("gcs-destination", dst)
|
||||
container = container.WithSecretVariable("GCS_DESTINATION", secret)
|
||||
|
||||
return container.WithExec([]string{"/bin/sh", "-c", "gcloud storage cp -r /src/* ${GCS_DESTINATION}"}), nil
|
||||
}
|
||||
|
||||
func GCSDownloadFile(d *dagger.Client, image string, auth GCPAuthenticator, url string) (*dagger.File, error) {
|
||||
var (
|
||||
container = d.Container().From(image)
|
||||
err error
|
||||
r = rand.Int()
|
||||
)
|
||||
|
||||
container, err = auth.Authenticate(d, container)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
secret := d.SetSecret("gcs-download-url", url)
|
||||
file := container.
|
||||
WithEnvVariable("RAND", strconv.Itoa(r)).
|
||||
WithSecretVariable("GCS_DOWNLOAD_URL", secret).
|
||||
WithExec([]string{"/bin/sh", "-c", "gcloud storage cp ${GCS_DOWNLOAD_URL} /src/file"}).
|
||||
File("/src/file")
|
||||
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func GCSAuth(d *dagger.Client, opts *GCPOpts) GCPAuthenticator {
|
||||
var auth GCPAuthenticator = &GCPInheritedAuth{}
|
||||
// The order of operations:
|
||||
// 1. Try to use base64 key.
|
||||
// 2. Try to use gcp-service-account-key (path to a file).
|
||||
// 3. Try mounting $XDG_CONFIG_HOME/gcloud
|
||||
if key := opts.ServiceAccountKeyBase64; key != "" {
|
||||
secret := d.SetSecret("gcp-sa-key-base64", key)
|
||||
// Write key to a file in an alpine container...
|
||||
file := d.Container().From("alpine").
|
||||
WithSecretVariable("GCP_SERVICE_ACCOUNT_KEY_BASE64", secret).
|
||||
WithExec([]string{"/bin/sh", "-c", "echo $GCP_SERVICE_ACCOUNT_KEY_BASE64 | base64 -d > /key.json"}).
|
||||
File("/key.json")
|
||||
|
||||
auth = NewGCPServiceAccountWithFile(file)
|
||||
} else if key := opts.ServiceAccountKey; key != "" {
|
||||
auth = NewGCPServiceAccount(key)
|
||||
}
|
||||
|
||||
return auth
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package containers
|
||||
|
||||
import "github.com/grafana/grafana/pkg/build/daggerbuild/cliutil"
|
||||
|
||||
type ProImageOpts struct {
|
||||
// Github token used to clone private repositories.
|
||||
GitHubToken string
|
||||
|
||||
// The path to a Grafana debian package.
|
||||
Deb string
|
||||
|
||||
// The Grafana version.
|
||||
GrafanaVersion string
|
||||
|
||||
// The docker image tag.
|
||||
ImageTag string
|
||||
|
||||
// The docker image repo.
|
||||
Repo string
|
||||
|
||||
// The release type.
|
||||
ReleaseType string
|
||||
|
||||
// True if the pro image should be pushed to the container registry.
|
||||
Push bool
|
||||
|
||||
// The container registry that the image should be pushed to. Required if Push is true.
|
||||
ContainerRegistry string
|
||||
}
|
||||
|
||||
func ProImageOptsFromFlags(c cliutil.CLIContext) *ProImageOpts {
|
||||
return &ProImageOpts{
|
||||
GitHubToken: c.String("github-token"),
|
||||
Deb: c.String("deb"),
|
||||
GrafanaVersion: c.String("grafana-version"),
|
||||
ImageTag: c.String("image-tag"),
|
||||
Repo: c.String("repo"),
|
||||
ReleaseType: c.String("release-type"),
|
||||
Push: c.Bool("push"),
|
||||
ContainerRegistry: c.String("registry"),
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
package containers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"dagger.io/dagger"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/cliutil"
|
||||
)
|
||||
|
||||
type PackageInputOpts struct {
|
||||
// Name is used when overriding the artifact that is being produced. This is used in very specific scenarios where
|
||||
// the source package's name does not match the package's metadata name.
|
||||
Name string
|
||||
Packages []string
|
||||
}
|
||||
|
||||
func PackageInputOptsFromFlags(c cliutil.CLIContext) *PackageInputOpts {
|
||||
return &PackageInputOpts{
|
||||
Name: c.String("name"),
|
||||
Packages: c.StringSlice("package"),
|
||||
}
|
||||
}
|
||||
|
||||
// GetPackage uses the PackageInputOpts to get a Grafana package, either from the local filesystem (if the package is of type 'file://...')
|
||||
// or Google Cloud Storage if the package is a 'gs://' URL.
|
||||
func GetPackages(ctx context.Context, d *dagger.Client, packageOpts *PackageInputOpts, gcpOpts *GCPOpts) ([]*dagger.File, error) {
|
||||
files := make([]*dagger.File, len(packageOpts.Packages))
|
||||
for i, pkg := range packageOpts.Packages {
|
||||
u, err := url.Parse(pkg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var file *dagger.File
|
||||
switch u.Scheme {
|
||||
case "file", "fs":
|
||||
p := strings.TrimPrefix(u.String(), u.Scheme+"://")
|
||||
f, err := getLocalPackage(ctx, d, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file = f
|
||||
case "gs":
|
||||
f, err := getGCSPackage(ctx, d, gcpOpts, u.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file = f
|
||||
default:
|
||||
return nil, fmt.Errorf("%w: %s", ErrorUnrecognizedScheme, u.Scheme)
|
||||
}
|
||||
|
||||
files[i] = file
|
||||
}
|
||||
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func getLocalPackage(ctx context.Context, d *dagger.Client, file string) (*dagger.File, error) {
|
||||
// pending https://github.com/dagger/dagger/issues/4745
|
||||
return d.Host().Directory(filepath.Dir(file)).File(filepath.Base(file)), nil
|
||||
}
|
||||
|
||||
func getGCSPackage(ctx context.Context, d *dagger.Client, opts *GCPOpts, gcsURL string) (*dagger.File, error) {
|
||||
auth := GCSAuth(d, opts)
|
||||
return GCSDownloadFile(d, GoogleCloudImage, auth, gcsURL)
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
package containers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"dagger.io/dagger"
|
||||
)
|
||||
|
||||
func publishLocalDir(ctx context.Context, dir *dagger.Directory, dst string) error {
|
||||
if _, err := dir.Export(ctx, dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func publishGCSDir(ctx context.Context, d *dagger.Client, dir *dagger.Directory, opts *GCPOpts, dst string) error {
|
||||
auth := GCSAuth(d, opts)
|
||||
uploader, err := GCSUploadDirectory(d, GoogleCloudImage, auth, dir, dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := ExitError(ctx, uploader); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// PublishDirectory publishes a directory to the given destination.
|
||||
func PublishDirectory(ctx context.Context, d *dagger.Client, dir *dagger.Directory, opts *GCPOpts, dst string) (string, error) {
|
||||
log.Println("Publishing directory", dst)
|
||||
u, err := url.Parse(dst)
|
||||
if err != nil {
|
||||
// If the destination URL is not a URL then we can assume that it's just a filepath.
|
||||
if err := publishLocalDir(ctx, dir, dst); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
switch u.Scheme {
|
||||
case "file", "fs":
|
||||
dst := strings.TrimPrefix(u.String(), u.Scheme+"://")
|
||||
if err := publishLocalDir(ctx, dir, dst); err != nil {
|
||||
return "", err
|
||||
}
|
||||
case "gs":
|
||||
if err := publishGCSDir(ctx, d, dir, opts, dst); err != nil {
|
||||
return "", err
|
||||
}
|
||||
default:
|
||||
return "", fmt.Errorf("%w: '%s'", ErrorUnrecognizedScheme, u.Scheme)
|
||||
}
|
||||
|
||||
return dst, nil
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package gcom
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/cliutil"
|
||||
)
|
||||
|
||||
// GCOMOpts are options used when making requests to grafana.com.
|
||||
type GCOMOpts struct {
|
||||
URL *url.URL
|
||||
DownloadURL *url.URL
|
||||
ApiKey string
|
||||
Beta bool
|
||||
Nightly bool
|
||||
}
|
||||
|
||||
func GCOMOptsFromFlags(c cliutil.CLIContext) (*GCOMOpts, error) {
|
||||
apiUrl, err := url.Parse(c.String("api-url"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
downloadUrl, err := url.Parse(c.String("download-url"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &GCOMOpts{
|
||||
URL: apiUrl,
|
||||
DownloadURL: downloadUrl,
|
||||
ApiKey: c.String("api-key"),
|
||||
Beta: c.Bool("beta"),
|
||||
Nightly: c.Bool("nightly"),
|
||||
}, nil
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
package gcom
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"dagger.io/dagger"
|
||||
)
|
||||
|
||||
type GCOMVersionPayload struct {
|
||||
Version string `json:"version"`
|
||||
ReleaseDate string `json:"releaseDate"`
|
||||
Stable bool `json:"stable"`
|
||||
Beta bool `json:"beta"`
|
||||
Nightly bool `json:"nightly"`
|
||||
WhatsNewURL string `json:"whatsNewUrl"`
|
||||
ReleaseNotesURL string `json:"releaseNotesUrl"`
|
||||
}
|
||||
|
||||
type GCOMPackagePayload struct {
|
||||
OS string `json:"os"`
|
||||
URL string `json:"url"`
|
||||
Sha256 string `json:"sha256"`
|
||||
Arch string `json:"arch"`
|
||||
}
|
||||
|
||||
// PublishGCOMVersion publishes a version to grafana.com.
|
||||
func PublishGCOMVersion(ctx context.Context, d *dagger.Client, versionPayload *GCOMVersionPayload, opts *GCOMOpts) (string, error) {
|
||||
versionApiUrl := opts.URL.JoinPath("/versions")
|
||||
|
||||
jsonVersionPayload, err := json.Marshal(versionPayload)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
apiKeySecret := d.SetSecret("gcom-api-key", opts.ApiKey)
|
||||
|
||||
return d.Container().From("alpine/curl").
|
||||
WithSecretVariable("GCOM_API_KEY", apiKeySecret).
|
||||
WithExec([]string{"/bin/sh", "-c", fmt.Sprintf(`curl -H "Content-Type: application/json" -H "Authorization: Bearer $GCOM_API_KEY" -d '%s' %s`, string(jsonVersionPayload), versionApiUrl.String())}).
|
||||
Stdout(ctx)
|
||||
}
|
||||
|
||||
// PublishGCOMPackage publishes a package to grafana.com.
|
||||
func PublishGCOMPackage(ctx context.Context, d *dagger.Client, packagePayload *GCOMPackagePayload, opts *GCOMOpts, version string) (string, error) {
|
||||
packagesApiUrl := opts.URL.JoinPath("/versions/", version, "/packages")
|
||||
|
||||
jsonPackagePayload, err := json.Marshal(packagePayload)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
apiKeySecret := d.SetSecret("gcom-api-key", opts.ApiKey)
|
||||
|
||||
return d.Container().From("alpine/curl").
|
||||
WithSecretVariable("GCOM_API_KEY", apiKeySecret).
|
||||
WithExec([]string{"/bin/sh", "-c", fmt.Sprintf(`curl -H "Content-Type: application/json" -H "Authorization: Bearer $GCOM_API_KEY" -d '%s' %s`, string(jsonPackagePayload), packagesApiUrl.String())}).
|
||||
Stdout(ctx)
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
package pipelines
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"dagger.io/dagger"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/containers"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/docker"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/sync/semaphore"
|
||||
)
|
||||
|
||||
func ImageManifest(tag string) string {
|
||||
log.Println(tag)
|
||||
log.Println(tag)
|
||||
log.Println(tag)
|
||||
log.Println(tag)
|
||||
manifest := strings.ReplaceAll(tag, "-image-tags", "")
|
||||
lastDash := strings.LastIndex(manifest, "-")
|
||||
return manifest[:lastDash]
|
||||
}
|
||||
|
||||
func LatestManifest(tag string) string {
|
||||
suffix := ""
|
||||
if strings.Contains(tag, "ubuntu") {
|
||||
suffix = "-ubuntu"
|
||||
}
|
||||
|
||||
manifest := strings.ReplaceAll(tag, "-image-tags", "")
|
||||
manifestImage := strings.Split(manifest, ":")[0]
|
||||
return strings.Join([]string{manifestImage, fmt.Sprintf("latest%s", suffix)}, ":")
|
||||
}
|
||||
|
||||
// PublishDocker is a pipeline that uses a grafana.docker.tar.gz as input and publishes a Docker image to a container registry or repository.
|
||||
// Grafana's Dockerfile should support supplying a tar.gz using a --build-arg.
|
||||
func PublishDocker(ctx context.Context, d *dagger.Client, args PipelineArgs) error {
|
||||
opts := args.DockerOpts
|
||||
packages, err := containers.GetPackages(ctx, d, args.PackageInputOpts, args.GCPOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
wg = &errgroup.Group{}
|
||||
sm = semaphore.NewWeighted(args.ConcurrencyOpts.Parallel)
|
||||
)
|
||||
|
||||
manifestTags := make(map[string][]string)
|
||||
for i, name := range args.PackageInputOpts.Packages {
|
||||
// For each package we retrieve the tags grafana-image-tags and grafana-oss-image-tags, or grafana-enterprise-image-tags
|
||||
format := opts.TagFormat
|
||||
if strings.Contains(name, "ubuntu") {
|
||||
format = opts.UbuntuTagFormat
|
||||
}
|
||||
|
||||
tarOpts := TarOptsFromFileName(name)
|
||||
|
||||
tags, err := docker.Tags(opts.Org, opts.Registry, []string{opts.Repository}, format, tarOpts.NameOpts())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Println(tags)
|
||||
for _, tag := range tags {
|
||||
// For each tag we publish an image and add the tag to the list of tags for a specific manifest
|
||||
// Since each package has a maximum of 2 tags, this for loop will only run twice on a worst case scenario
|
||||
manifest := ImageManifest(tag)
|
||||
manifestTags[manifest] = append(manifestTags[manifest], tag)
|
||||
|
||||
if opts.Latest {
|
||||
manifest := LatestManifest(tag)
|
||||
manifestTags[manifest] = append(manifestTags[manifest], tag)
|
||||
}
|
||||
|
||||
wg.Go(PublishPackageImageFunc(ctx, sm, d, packages[i], tag, opts))
|
||||
}
|
||||
}
|
||||
|
||||
if err := wg.Wait(); err != nil {
|
||||
// Wait for all images to be published
|
||||
return err
|
||||
}
|
||||
|
||||
for manifest, tags := range manifestTags {
|
||||
// Publish each manifest
|
||||
wg.Go(PublishDockerManifestFunc(ctx, sm, d, manifest, tags, opts))
|
||||
}
|
||||
|
||||
return wg.Wait()
|
||||
}
|
||||
|
||||
func PublishPackageImageFunc(ctx context.Context, sm *semaphore.Weighted, d *dagger.Client, pkg *dagger.File, tag string, opts *docker.DockerOpts) func() error {
|
||||
return func() error {
|
||||
log.Printf("[%s] Attempting to publish image", tag)
|
||||
log.Printf("[%s] Acquiring semaphore", tag)
|
||||
if err := sm.Acquire(ctx, 1); err != nil {
|
||||
return fmt.Errorf("failed to acquire semaphore: %w", err)
|
||||
}
|
||||
defer sm.Release(1)
|
||||
log.Printf("[%s] Acquired semaphore", tag)
|
||||
|
||||
log.Printf("[%s] Publishing image", tag)
|
||||
out, err := docker.PublishPackageImage(ctx, d, pkg, tag, opts.Username, opts.Password, opts.Registry)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[%s] error: %w", tag, err)
|
||||
}
|
||||
log.Printf("[%s] Done publishing image", tag)
|
||||
|
||||
if _, err := fmt.Fprintln(Stdout, out); err != nil {
|
||||
return fmt.Errorf("error writing to stdout: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func PublishDockerManifestFunc(ctx context.Context, sm *semaphore.Weighted, d *dagger.Client, manifest string, tags []string, opts *docker.DockerOpts) func() error {
|
||||
return func() error {
|
||||
log.Printf("[%s] Attempting to publish manifest", manifest)
|
||||
log.Printf("[%s] Acquiring semaphore", manifest)
|
||||
if err := sm.Acquire(ctx, 1); err != nil {
|
||||
return fmt.Errorf("failed to acquire semaphore: %w", err)
|
||||
}
|
||||
defer sm.Release(1)
|
||||
log.Printf("[%s] Acquired semaphore", manifest)
|
||||
|
||||
log.Printf("[%s] Publishing manifest", manifest)
|
||||
out, err := docker.PublishManifest(ctx, d, manifest, tags, opts.Username, opts.Password, opts.Registry)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[%s] error: %w", manifest, err)
|
||||
}
|
||||
log.Printf("[%s] Done publishing manifest", manifest)
|
||||
|
||||
if _, err := fmt.Fprintln(Stdout, out); err != nil {
|
||||
return fmt.Errorf("error writing to stdout: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package pipelines_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/pipelines"
|
||||
)
|
||||
|
||||
func TestImageManifest(t *testing.T) {
|
||||
manifests := map[string]string{
|
||||
"docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-amd64": "docker.io/grafana/grafana:1.2.3-test.1.2.3",
|
||||
"docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-amd64": "docker.io/grafana/grafana-oss:1.2.3-test.1.2.3",
|
||||
"docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-arm64": "docker.io/grafana/grafana:1.2.3-test.1.2.3",
|
||||
"docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-arm64": "docker.io/grafana/grafana-oss:1.2.3-test.1.2.3",
|
||||
"docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-ubuntu-amd64": "docker.io/grafana/grafana:1.2.3-test.1.2.3-ubuntu",
|
||||
"docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-ubuntu-amd64": "docker.io/grafana/grafana-oss:1.2.3-test.1.2.3-ubuntu",
|
||||
"docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-ubuntu-arm64": "docker.io/grafana/grafana:1.2.3-test.1.2.3-ubuntu",
|
||||
"docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-ubuntu-arm64": "docker.io/grafana/grafana-oss:1.2.3-test.1.2.3-ubuntu",
|
||||
"docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-amd64": "docker.io/grafana/grafana-enterprise:1.2.3-test.1.2.3",
|
||||
"docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-arm64": "docker.io/grafana/grafana-enterprise:1.2.3-test.1.2.3",
|
||||
"docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-ubuntu-amd64": "docker.io/grafana/grafana-enterprise:1.2.3-test.1.2.3-ubuntu",
|
||||
"docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-ubuntu-arm64": "docker.io/grafana/grafana-enterprise:1.2.3-test.1.2.3-ubuntu",
|
||||
}
|
||||
|
||||
for k, v := range manifests {
|
||||
if n := pipelines.ImageManifest(k); n != v {
|
||||
t.Errorf("Expected '%s' manifest to equal '%s' but got '%s'", k, v, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLatestManifest(t *testing.T) {
|
||||
manifests := map[string]string{
|
||||
"docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-amd64": "docker.io/grafana/grafana:latest",
|
||||
"docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-amd64": "docker.io/grafana/grafana-oss:latest",
|
||||
"docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-arm64": "docker.io/grafana/grafana:latest",
|
||||
"docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-arm64": "docker.io/grafana/grafana-oss:latest",
|
||||
"docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-ubuntu-amd64": "docker.io/grafana/grafana:latest-ubuntu",
|
||||
"docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-ubuntu-amd64": "docker.io/grafana/grafana-oss:latest-ubuntu",
|
||||
"docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-ubuntu-arm64": "docker.io/grafana/grafana:latest-ubuntu",
|
||||
"docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-ubuntu-arm64": "docker.io/grafana/grafana-oss:latest-ubuntu",
|
||||
"docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-amd64": "docker.io/grafana/grafana-enterprise:latest",
|
||||
"docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-arm64": "docker.io/grafana/grafana-enterprise:latest",
|
||||
"docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-ubuntu-amd64": "docker.io/grafana/grafana-enterprise:latest-ubuntu",
|
||||
"docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-ubuntu-arm64": "docker.io/grafana/grafana-enterprise:latest-ubuntu",
|
||||
}
|
||||
|
||||
for k, v := range manifests {
|
||||
if n := pipelines.LatestManifest(k); n != v {
|
||||
t.Errorf("Expected '%s' manifest to equal '%s' but got '%s'", k, v, n)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,246 +0,0 @@
|
|||
package pipelines_test
|
||||
|
||||
//
|
||||
// func TestImageName(t *testing.T) {
|
||||
// // Normally I don't advocate for abstracting tests using test cases
|
||||
// // but I think in this case I would really like to get a clearer view into what docker image tags will be produced.
|
||||
// // Be sure that if you add additional test cases to this that you don't use formatting or concatenation; it should be obvious when looking at the test
|
||||
// // what the expected output should be. And that value should not change based on another value.
|
||||
// type tc struct {
|
||||
// Description string
|
||||
// Tags []string
|
||||
// BaseImage pipelines.BaseImage
|
||||
// DockerOpts *containers.DockerOpts
|
||||
// TarOpts pipelines.TarFileOpts
|
||||
// }
|
||||
//
|
||||
// var (
|
||||
// version = "v1.2.3-test.1.2.3"
|
||||
// )
|
||||
//
|
||||
// cases := []tc{
|
||||
// {
|
||||
// Description: "Grafana docker images are created for both the 'docker.io/grafana/grafana-image-tags' and 'docker.io/grafana/grafana-oss-image-tags' repositories. Alpine images have no suffix.",
|
||||
// TarOpts: pipelines.TarFileOpts{
|
||||
// Edition: "",
|
||||
// Distro: "linux/amd64",
|
||||
// Version: version,
|
||||
// },
|
||||
// DockerOpts: &containers.DockerOpts{
|
||||
// Org: "grafana",
|
||||
// Registry: "docker.io",
|
||||
// TagFormat: pipelines.DefaultTagFormat,
|
||||
// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat,
|
||||
// },
|
||||
// BaseImage: pipelines.BaseImageAlpine,
|
||||
// Tags: []string{
|
||||
// "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-amd64",
|
||||
// "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-amd64",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// Description: "Grafana docker images are created for both the 'docker.io/grafana/grafana-image-tags' and 'docker.io/grafana/grafana-oss-image-tags' repositories. ARM64 images have a -arm64 suffix. Alpine images have no suffix.",
|
||||
// TarOpts: pipelines.TarFileOpts{
|
||||
// Edition: "",
|
||||
// Distro: "linux/arm64",
|
||||
// Version: version,
|
||||
// },
|
||||
// DockerOpts: &containers.DockerOpts{
|
||||
// Org: "grafana",
|
||||
// Registry: "docker.io",
|
||||
// TagFormat: pipelines.DefaultTagFormat,
|
||||
// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat,
|
||||
// },
|
||||
// BaseImage: pipelines.BaseImageAlpine,
|
||||
// Tags: []string{
|
||||
// "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-arm64",
|
||||
// "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-arm64",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// Description: "Grafana docker images are created for both the 'docker.io/grafana/grafana-image-tags' and 'docker.io/grafana/grafana-oss-image-tags' repositories. Ubuntu images have a '-ubuntu' suffix.",
|
||||
// TarOpts: pipelines.TarFileOpts{
|
||||
// Edition: "",
|
||||
// Distro: "linux/amd64",
|
||||
// Version: version,
|
||||
// },
|
||||
// DockerOpts: &containers.DockerOpts{
|
||||
// Org: "grafana",
|
||||
// Registry: "docker.io",
|
||||
// TagFormat: pipelines.DefaultTagFormat,
|
||||
// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat,
|
||||
// },
|
||||
// BaseImage: pipelines.BaseImageUbuntu,
|
||||
// Tags: []string{
|
||||
// "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-ubuntu-amd64",
|
||||
// "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-ubuntu-amd64",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// Description: "Grafana docker images are created for both the 'docker.io/grafana/grafana-image-tags' and 'docker.io/grafana/grafana-oss-image-tags' repositories. ARM64 images have an -arm64 suffix. Ubuntu images have a '-ubuntu' suffix.",
|
||||
// TarOpts: pipelines.TarFileOpts{
|
||||
// Edition: "",
|
||||
// Distro: "linux/arm64",
|
||||
// Version: version,
|
||||
// },
|
||||
// DockerOpts: &containers.DockerOpts{
|
||||
// Org: "grafana",
|
||||
// Registry: "docker.io",
|
||||
// TagFormat: pipelines.DefaultTagFormat,
|
||||
// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat,
|
||||
// },
|
||||
// BaseImage: pipelines.BaseImageUbuntu,
|
||||
// Tags: []string{
|
||||
// "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-ubuntu-arm64",
|
||||
// "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-ubuntu-arm64",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// Description: "Enterprise docker images are created for only the docker.io/grafana/grafana-enterprise-image-tags repository. Alpine images have no suffix.",
|
||||
// TarOpts: pipelines.TarFileOpts{
|
||||
// Edition: "enterprise",
|
||||
// Distro: "linux/amd64",
|
||||
// Version: version,
|
||||
// },
|
||||
// DockerOpts: &containers.DockerOpts{
|
||||
// Org: "grafana",
|
||||
// Registry: "docker.io",
|
||||
// TagFormat: pipelines.DefaultTagFormat,
|
||||
// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat,
|
||||
// },
|
||||
// BaseImage: pipelines.BaseImageAlpine,
|
||||
// Tags: []string{
|
||||
// "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-amd64",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// Description: "Enterprise docker images are created for only the docker.io/grafana/grafana-enterprise-image-tags repository. ARM64 images have an -arm64 suffix. Alpine images have no suffix.",
|
||||
// TarOpts: pipelines.TarFileOpts{
|
||||
// Edition: "enterprise",
|
||||
// Distro: "linux/arm64",
|
||||
// Version: version,
|
||||
// },
|
||||
// DockerOpts: &containers.DockerOpts{
|
||||
// Org: "grafana",
|
||||
// Registry: "docker.io",
|
||||
// TagFormat: pipelines.DefaultTagFormat,
|
||||
// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat,
|
||||
// },
|
||||
// BaseImage: pipelines.BaseImageAlpine,
|
||||
// Tags: []string{
|
||||
// "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-arm64",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// Description: "Enterprise docker images are created for only the docker.io/grafana/grafana-enterprise-image-tags repository. Ubuntu images have a '-ubuntu' suffix.",
|
||||
// TarOpts: pipelines.TarFileOpts{
|
||||
// Edition: "enterprise",
|
||||
// Distro: "linux/amd64",
|
||||
// Version: version,
|
||||
// },
|
||||
// DockerOpts: &containers.DockerOpts{
|
||||
// Org: "grafana",
|
||||
// Registry: "docker.io",
|
||||
// TagFormat: pipelines.DefaultTagFormat,
|
||||
// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat,
|
||||
// },
|
||||
// BaseImage: pipelines.BaseImageUbuntu,
|
||||
// Tags: []string{
|
||||
// "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-ubuntu-amd64",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// Description: "Enterprise docker images are created for only the docker.io/grafana/grafana-enterprise-image-tags repository. ARM64 images have an -arm64 suffix. Ubuntu images have a '-ubuntu' suffix.",
|
||||
// TarOpts: pipelines.TarFileOpts{
|
||||
// Edition: "enterprise",
|
||||
// Distro: "linux/arm64",
|
||||
// Version: version,
|
||||
// },
|
||||
// DockerOpts: &containers.DockerOpts{
|
||||
// Org: "grafana",
|
||||
// Registry: "docker.io",
|
||||
// TagFormat: pipelines.DefaultTagFormat,
|
||||
// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat,
|
||||
// },
|
||||
// BaseImage: pipelines.BaseImageUbuntu,
|
||||
// Tags: []string{
|
||||
// "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-ubuntu-arm64",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// Description: "Grafana docker images are created for both the 'registry.io/org/grafana-image-tags' and 'registry.io/org/grafana-oss-image-tags' repositories. Alpine images have no suffix.",
|
||||
// TarOpts: pipelines.TarFileOpts{
|
||||
// Edition: "",
|
||||
// Distro: "linux/amd64",
|
||||
// Version: version,
|
||||
// },
|
||||
// DockerOpts: &containers.DockerOpts{
|
||||
// Org: "org",
|
||||
// Registry: "registry.io",
|
||||
// TagFormat: pipelines.DefaultTagFormat,
|
||||
// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat,
|
||||
// },
|
||||
// BaseImage: pipelines.BaseImageAlpine,
|
||||
// Tags: []string{
|
||||
// "registry.io/org/grafana-image-tags:1.2.3-test.1.2.3-amd64",
|
||||
// "registry.io/org/grafana-oss-image-tags:1.2.3-test.1.2.3-amd64",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// Description: "Grafana docker images are created for only the 'registry.io/org/grafana-dev' repository. Alpine images have no suffix.",
|
||||
// TarOpts: pipelines.TarFileOpts{
|
||||
// Edition: "",
|
||||
// Distro: "linux/amd64",
|
||||
// Version: version,
|
||||
// },
|
||||
// DockerOpts: &containers.DockerOpts{
|
||||
// Org: "org",
|
||||
// Registry: "registry.io",
|
||||
// Repository: "grafana-dev",
|
||||
// TagFormat: pipelines.DefaultTagFormat,
|
||||
// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat,
|
||||
// },
|
||||
// BaseImage: pipelines.BaseImageAlpine,
|
||||
// Tags: []string{
|
||||
// "registry.io/org/grafana-dev:1.2.3-test.1.2.3-amd64",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// Description: "Grafana docker images are created for only the 'registry.io/org/grafana-dev' repository.",
|
||||
// TarOpts: pipelines.TarFileOpts{
|
||||
// Edition: "",
|
||||
// Distro: "linux/amd64",
|
||||
// Version: version,
|
||||
// },
|
||||
// DockerOpts: &containers.DockerOpts{
|
||||
// Org: "org",
|
||||
// Registry: "registry.io",
|
||||
// Repository: "grafana-dev",
|
||||
// TagFormat: pipelines.DefaultTagFormat,
|
||||
// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat,
|
||||
// },
|
||||
// BaseImage: pipelines.BaseImageUbuntu,
|
||||
// Tags: []string{
|
||||
// "registry.io/org/grafana-dev:1.2.3-test.1.2.3-ubuntu-amd64",
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// for n, test := range cases {
|
||||
// t.Run(fmt.Sprintf("[%d / %d] %s", n+1, len(cases), test.Description), func(t *testing.T) {
|
||||
// expect := sort.StringSlice(test.Tags)
|
||||
// res, err := pipelines.GrafanaImageTags(test.BaseImage, test.DockerOpts, test.TarOpts)
|
||||
// if err != nil {
|
||||
// t.Fatal("Unexpected error:", err.Error())
|
||||
// }
|
||||
//
|
||||
// for i := range expect {
|
||||
// e := expect[i]
|
||||
// r := res[i]
|
||||
// if e != r {
|
||||
// t.Errorf("[%d / %d]\nExpected '%s'\nReceived '%s'", i+1, len(expect), e, r)
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
|
@ -1,154 +0,0 @@
|
|||
package pipelines
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"dagger.io/dagger"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/backend"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/containers"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/gcom"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/sync/semaphore"
|
||||
)
|
||||
|
||||
func VersionPayloadFromFileName(name string, opts *gcom.GCOMOpts) *gcom.GCOMVersionPayload {
|
||||
var (
|
||||
tarOpts = TarOptsFromFileName(name)
|
||||
splitVersion = strings.Split(tarOpts.Version, ".")
|
||||
stable = true
|
||||
nightly = false
|
||||
beta = false
|
||||
)
|
||||
|
||||
if opts.Beta {
|
||||
stable = false
|
||||
beta = true
|
||||
}
|
||||
if opts.Nightly {
|
||||
stable = false
|
||||
beta = false
|
||||
nightly = true
|
||||
}
|
||||
|
||||
return &gcom.GCOMVersionPayload{
|
||||
Version: tarOpts.Version,
|
||||
ReleaseDate: time.Now().Format(time.RFC3339Nano),
|
||||
Stable: stable,
|
||||
Beta: beta,
|
||||
Nightly: nightly,
|
||||
WhatsNewURL: fmt.Sprintf("https://grafana.com/docs/grafana/next/whatsnew/whats-new-in-v%s-%s/", splitVersion[0], splitVersion[1]),
|
||||
ReleaseNotesURL: "https://grafana.com/docs/grafana/next/release-notes/",
|
||||
}
|
||||
}
|
||||
|
||||
func PackagePayloadFromFile(ctx context.Context, d *dagger.Client, name string, file *dagger.File, opts *gcom.GCOMOpts) (*gcom.GCOMPackagePayload, error) {
|
||||
tarOpts := TarOptsFromFileName(name)
|
||||
ext := filepath.Ext(name)
|
||||
os, _ := backend.OSAndArch(tarOpts.Distro)
|
||||
arch := strings.ReplaceAll(backend.FullArch(tarOpts.Distro), "/", "")
|
||||
|
||||
if os == "windows" {
|
||||
os = "win"
|
||||
}
|
||||
|
||||
if ext == ".deb" {
|
||||
os = "deb"
|
||||
}
|
||||
if ext == ".rpm" {
|
||||
os = "rhel"
|
||||
}
|
||||
if ext == ".exe" {
|
||||
os = "win-installer"
|
||||
}
|
||||
|
||||
sha256, err := containers.Sha256(d, file).Contents(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &gcom.GCOMPackagePayload{
|
||||
OS: os,
|
||||
URL: opts.DownloadURL.JoinPath(name).String(),
|
||||
Sha256: sha256,
|
||||
Arch: arch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func PublishGCOM(ctx context.Context, d *dagger.Client, args PipelineArgs) error {
|
||||
var (
|
||||
opts = args.GCOMOpts
|
||||
wg = &errgroup.Group{}
|
||||
sm = semaphore.NewWeighted(args.ConcurrencyOpts.Parallel)
|
||||
)
|
||||
|
||||
packages, err := containers.GetPackages(ctx, d, args.PackageInputOpts, args.GCPOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Extract the package versions
|
||||
versionPayloads := make(map[string]*gcom.GCOMVersionPayload)
|
||||
for _, name := range args.PackageInputOpts.Packages {
|
||||
tarOpts := TarOptsFromFileName(name)
|
||||
if _, ok := versionPayloads[tarOpts.Version]; !ok {
|
||||
log.Printf("[%s] Building version payload", tarOpts.Version)
|
||||
versionPayloads[tarOpts.Version] = VersionPayloadFromFileName(name, opts)
|
||||
}
|
||||
}
|
||||
|
||||
// Publish each version only once
|
||||
for _, p := range versionPayloads {
|
||||
log.Printf("[%s] Attempting to publish version", p.Version)
|
||||
out, err := gcom.PublishGCOMVersion(ctx, d, p, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("[%s] Done publishing version", p.Version)
|
||||
if _, err := fmt.Fprintln(Stdout, strings.ReplaceAll(out, "\n", "")); err != nil {
|
||||
return fmt.Errorf("error writing to stdout: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Publish the package(s)
|
||||
for i, name := range args.PackageInputOpts.Packages {
|
||||
wg.Go(PublishGCOMPackageFunc(ctx, sm, d, opts, name, packages[i]))
|
||||
}
|
||||
return wg.Wait()
|
||||
}
|
||||
|
||||
func PublishGCOMPackageFunc(ctx context.Context, sm *semaphore.Weighted, d *dagger.Client, opts *gcom.GCOMOpts, path string, file *dagger.File) func() error {
|
||||
return func() error {
|
||||
name := filepath.Base(path)
|
||||
tarOpts := TarOptsFromFileName(name)
|
||||
log.Printf("[%s] Attempting to publish package", name)
|
||||
log.Printf("[%s] Acquiring semaphore", name)
|
||||
if err := sm.Acquire(ctx, 1); err != nil {
|
||||
return fmt.Errorf("failed to acquire semaphore: %w", err)
|
||||
}
|
||||
defer sm.Release(1)
|
||||
log.Printf("[%s] Acquired semaphore", name)
|
||||
|
||||
log.Printf("[%s] Building package payload", name)
|
||||
packagePayload, err := PackagePayloadFromFile(ctx, d, name, file, opts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[%s] error: %w", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[%s] Publishing package", name)
|
||||
out, err := gcom.PublishGCOMPackage(ctx, d, packagePayload, opts, tarOpts.Version)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[%s] error: %w", name, err)
|
||||
}
|
||||
log.Printf("[%s] Done publishing package", name)
|
||||
|
||||
if _, err := fmt.Fprintln(Stdout, strings.ReplaceAll(out, "\n", "")); err != nil {
|
||||
return fmt.Errorf("error writing to stdout: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
package pipelines
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"dagger.io/dagger"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/containers"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/frontend"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/sync/semaphore"
|
||||
)
|
||||
|
||||
func PublishNPM(ctx context.Context, d *dagger.Client, args PipelineArgs) error {
|
||||
var (
|
||||
wg = &errgroup.Group{}
|
||||
sm = semaphore.NewWeighted(args.ConcurrencyOpts.Parallel)
|
||||
)
|
||||
|
||||
packages, err := containers.GetPackages(ctx, d, args.PackageInputOpts, args.GCPOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Extract the package(s)
|
||||
for i := range args.PackageInputOpts.Packages {
|
||||
var (
|
||||
// name = ReplaceExt(v, "")
|
||||
targz = packages[i]
|
||||
)
|
||||
|
||||
artifacts := containers.ExtractedArchive(d, targz).Directory("npm-artifacts")
|
||||
|
||||
entries, err := artifacts.Entries(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, path := range entries {
|
||||
wg.Go(PublishNPMFunc(ctx, sm, d, artifacts.File(path), path, args.NpmToken, args.NpmRegistry, args.NpmTags))
|
||||
}
|
||||
}
|
||||
return wg.Wait()
|
||||
}
|
||||
|
||||
func PublishNPMFunc(ctx context.Context, sm *semaphore.Weighted, d *dagger.Client, pkg *dagger.File, path, token, registry string, tags []string) func() error {
|
||||
return func() error {
|
||||
log.Printf("[%s] Attempting to publish package", path)
|
||||
log.Printf("[%s] Acquiring semaphore", path)
|
||||
if err := sm.Acquire(ctx, 1); err != nil {
|
||||
return fmt.Errorf("failed to acquire semaphore: %w", err)
|
||||
}
|
||||
defer sm.Release(1)
|
||||
log.Printf("[%s] Acquired semaphore", path)
|
||||
|
||||
log.Printf("[%s] Publishing package", path)
|
||||
out, err := frontend.PublishNPM(ctx, d, pkg, token, registry, tags)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[%s] error: %w", path, err)
|
||||
}
|
||||
log.Printf("[%s] Done publishing package", path)
|
||||
|
||||
if _, err := fmt.Fprintln(Stdout, out); err != nil {
|
||||
return fmt.Errorf("error writing to stdout: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
package pipelines
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/backend"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/packages"
|
||||
)
|
||||
|
||||
type TarFileOpts struct {
|
||||
// Name is the name of the product in the package. 99% of the time, this will be "grafana" or "grafana-enterprise".
|
||||
Name string
|
||||
Version string
|
||||
BuildID string
|
||||
// Edition is the flavor text after "grafana-", like "enterprise".
|
||||
Edition string
|
||||
Distro backend.Distribution
|
||||
Suffix string
|
||||
}
|
||||
|
||||
func (opts *TarFileOpts) NameOpts() packages.NameOpts {
|
||||
return packages.NameOpts{
|
||||
// Name is the name of the product in the package. 99% of the time, this will be "grafana" or "grafana-enterprise".
|
||||
Name: packages.Name(opts.Name),
|
||||
Version: opts.Version,
|
||||
BuildID: opts.BuildID,
|
||||
Distro: opts.Distro,
|
||||
}
|
||||
}
|
||||
|
||||
func WithoutExt(name string) string {
|
||||
ext := filepath.Ext(name)
|
||||
n := strings.TrimSuffix(name, ext)
|
||||
|
||||
// Explicitly handle `.gz` which might will also probably have a `.tar` extension as well.
|
||||
if ext == ".gz" {
|
||||
n = strings.TrimSuffix(n, ".ubuntu.docker.tar")
|
||||
n = strings.TrimSuffix(n, ".docker.tar")
|
||||
n = strings.TrimSuffix(n, ".tar")
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
func TarOptsFromFileName(filename string) TarFileOpts {
|
||||
filename = filepath.Base(filename)
|
||||
n := WithoutExt(filename)
|
||||
components := strings.Split(n, "_")
|
||||
if len(components) != 5 {
|
||||
return TarFileOpts{}
|
||||
}
|
||||
|
||||
var (
|
||||
name = components[0]
|
||||
version = components[1]
|
||||
buildID = components[2]
|
||||
os = components[3]
|
||||
arch = components[4]
|
||||
)
|
||||
if archv := strings.Split(arch, "-"); len(archv) == 2 {
|
||||
// The reverse operation of removing the 'v' for 'arm' because the golang environment variable
|
||||
// GOARM doesn't want it, but the docker --platform flag either doesn't care or does want it.
|
||||
if archv[0] == "arm" {
|
||||
archv[1] = "v" + archv[1]
|
||||
}
|
||||
|
||||
// arm-7 should become arm/v7
|
||||
arch = strings.Join([]string{archv[0], archv[1]}, "/")
|
||||
}
|
||||
edition := ""
|
||||
suffix := ""
|
||||
if n := strings.Split(name, "-"); len(n) != 1 {
|
||||
edition = strings.Join(n[1:], "-")
|
||||
suffix = fmt.Sprintf("-%s", n[1])
|
||||
}
|
||||
|
||||
return TarFileOpts{
|
||||
Name: name,
|
||||
Edition: edition,
|
||||
Version: version,
|
||||
BuildID: buildID,
|
||||
Distro: backend.Distribution(strings.Join([]string{os, arch}, "/")),
|
||||
Suffix: suffix,
|
||||
}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
package pipelines_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/backend"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/pipelines"
|
||||
)
|
||||
|
||||
func TestWithoutExt(t *testing.T) {
|
||||
names := map[string]string{
|
||||
"grafana_v1.0.1-test_333_plan9_amd64.tar.gz": "grafana_v1.0.1-test_333_plan9_amd64",
|
||||
"grafana-enterprise_v1.0.1-test_333_plan9_amd64.tar.gz": "grafana-enterprise_v1.0.1-test_333_plan9_amd64",
|
||||
"grafana-enterprise_v1.0.1-test_333_plan9_arm-6.tar.gz": "grafana-enterprise_v1.0.1-test_333_plan9_arm-6",
|
||||
"grafana-enterprise_v1.0.1-test_333_plan9_amd64.deb": "grafana-enterprise_v1.0.1-test_333_plan9_amd64",
|
||||
"grafana-enterprise_v1.0.1-test_333_plan9_arm-6.deb": "grafana-enterprise_v1.0.1-test_333_plan9_arm-6",
|
||||
"grafana-enterprise_v1.0.1-test_333_plan9_arm-6.docker.tar.gz": "grafana-enterprise_v1.0.1-test_333_plan9_arm-6",
|
||||
"grafana-enterprise_v1.0.1-test_333_plan9_arm-6.ubuntu.docker.tar.gz": "grafana-enterprise_v1.0.1-test_333_plan9_arm-6",
|
||||
}
|
||||
|
||||
for k, v := range names {
|
||||
if n := pipelines.WithoutExt(k); n != v {
|
||||
t.Errorf("Expected '%s' without file name to equal '%s' but got '%s'", k, v, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptsFromFile(t *testing.T) {
|
||||
t.Run("It should get the correct tar file opts from a valid name", func(t *testing.T) {
|
||||
name := "grafana-enterprise_v1.0.1-test_333_plan9_arm-6.tar.gz"
|
||||
distro := backend.Distribution("plan9/arm/v6")
|
||||
expect := pipelines.TarFileOpts{
|
||||
Edition: "enterprise",
|
||||
Version: "v1.0.1-test",
|
||||
BuildID: "333",
|
||||
Distro: distro,
|
||||
}
|
||||
got := pipelines.TarOptsFromFileName(name)
|
||||
if got.Edition != expect.Edition {
|
||||
t.Errorf("got.Edition != expect.Edition, expected '%s'", expect.Edition)
|
||||
}
|
||||
if got.Version != expect.Version {
|
||||
t.Errorf("got.Version != expect.Version, expected '%s', got '%s'", expect.Version, got.Version)
|
||||
}
|
||||
if got.BuildID != expect.BuildID {
|
||||
t.Errorf("got.BuildID != expect.BuildID, expected '%s', got '%s'", expect.BuildID, got.BuildID)
|
||||
}
|
||||
if got.Distro != expect.Distro {
|
||||
t.Errorf("got.Distro != expect.Distro, expected '%s', got '%s'", expect.Distro, got.Distro)
|
||||
}
|
||||
})
|
||||
t.Run("It should consider only the basename", func(t *testing.T) {
|
||||
name := "somewhere/grafana-enterprise_v1.0.1-test_333_plan9_arm-6.tar.gz"
|
||||
distro := backend.Distribution("plan9/arm/v6")
|
||||
expect := pipelines.TarFileOpts{
|
||||
Edition: "enterprise",
|
||||
Version: "v1.0.1-test",
|
||||
BuildID: "333",
|
||||
Distro: distro,
|
||||
}
|
||||
got := pipelines.TarOptsFromFileName(name)
|
||||
if got.Edition != expect.Edition {
|
||||
t.Errorf("got.Edition != expect.Edition, expected '%s'", expect.Edition)
|
||||
}
|
||||
if got.Version != expect.Version {
|
||||
t.Errorf("got.Version != expect.Version, expected '%s', got '%s'", expect.Version, got.Version)
|
||||
}
|
||||
if got.BuildID != expect.BuildID {
|
||||
t.Errorf("got.BuildID != expect.BuildID, expected '%s', got '%s'", expect.BuildID, got.BuildID)
|
||||
}
|
||||
if got.Distro != expect.Distro {
|
||||
t.Errorf("got.Distro != expect.Distro, expected '%s', got '%s'", expect.Distro, got.Distro)
|
||||
}
|
||||
})
|
||||
t.Run("It should support editions with multiple hyphens", func(t *testing.T) {
|
||||
name := "somewhere/grafana-enterprise-rpi_v1.0.1-test_333_plan9_arm-6.tar.gz"
|
||||
distro := backend.Distribution("plan9/arm/v6")
|
||||
expect := pipelines.TarFileOpts{
|
||||
Edition: "enterprise-rpi",
|
||||
Version: "v1.0.1-test",
|
||||
BuildID: "333",
|
||||
Distro: distro,
|
||||
}
|
||||
got := pipelines.TarOptsFromFileName(name)
|
||||
if got.Edition != expect.Edition {
|
||||
t.Errorf("got.Edition != expect.Edition, expected '%s', got '%s'", expect.Edition, got.Edition)
|
||||
}
|
||||
if got.Version != expect.Version {
|
||||
t.Errorf("got.Version != expect.Version, expected '%s', got '%s'", expect.Version, got.Version)
|
||||
}
|
||||
if got.BuildID != expect.BuildID {
|
||||
t.Errorf("got.BuildID != expect.BuildID, expected '%s', got '%s'", expect.BuildID, got.BuildID)
|
||||
}
|
||||
if got.Distro != expect.Distro {
|
||||
t.Errorf("got.Distro != expect.Distro, expected '%s', got '%s'", expect.Distro, got.Distro)
|
||||
}
|
||||
})
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package pipelines
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"dagger.io/dagger"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/containers"
|
||||
)
|
||||
|
||||
// PublishPackage takes one or multiple grafana.tar.gz as input and publishes it to a set destination.
|
||||
func PublishPackage(ctx context.Context, d *dagger.Client, args PipelineArgs) error {
|
||||
packages, err := containers.GetPackages(ctx, d, args.PackageInputOpts, args.GCPOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c := d.Container().From("alpine")
|
||||
for i, name := range args.PackageInputOpts.Packages {
|
||||
c = c.WithFile("/dist/"+filepath.Base(name), packages[i])
|
||||
}
|
||||
|
||||
dst, err := containers.PublishDirectory(ctx, d, c.Directory("dist"), args.GCPOpts, args.PublishOpts.Destination)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := fmt.Fprintln(os.Stdout, dst); err != nil {
|
||||
return fmt.Errorf("error writing to stdout: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
package pipelines_test
|
|
@ -1,147 +0,0 @@
|
|||
// package pipelines has functions and types that orchestrate containers.
|
||||
package pipelines
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"dagger.io/dagger"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/cliutil"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/containers"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/docker"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/gcom"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/gpg"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
type PipelineFunc func(context.Context, *dagger.Client, *dagger.Directory, PipelineArgs) error
|
||||
type PipelineFuncWithPackageInput func(context.Context, *dagger.Client, PipelineArgs) error
|
||||
|
||||
func DockerOptsFromFlags(c cliutil.CLIContext) *docker.DockerOpts {
|
||||
return &docker.DockerOpts{
|
||||
Registry: c.String("registry"),
|
||||
AlpineBase: c.String("alpine-base"),
|
||||
UbuntuBase: c.String("ubuntu-base"),
|
||||
Username: c.String("username"),
|
||||
Password: c.String("password"),
|
||||
Org: c.String("org"),
|
||||
Repository: c.String("repo"),
|
||||
Latest: c.Bool("latest"),
|
||||
TagFormat: c.String("tag-format"),
|
||||
UbuntuTagFormat: c.String("ubuntu-tag-format"),
|
||||
}
|
||||
}
|
||||
|
||||
type ConcurrencyOpts struct {
|
||||
Parallel int64
|
||||
}
|
||||
|
||||
func ConcurrencyOptsFromFlags(c cliutil.CLIContext) *ConcurrencyOpts {
|
||||
return &ConcurrencyOpts{
|
||||
Parallel: c.Int64("parallel"),
|
||||
}
|
||||
}
|
||||
|
||||
type PipelineArgs struct {
|
||||
// These arguments are ones that are available at the global level.
|
||||
Verbose bool
|
||||
|
||||
// Platform, where applicable, specifies what platform (linux/arm64, for example) to run the dagger containers on.
|
||||
// This should really only be used if you know what you're doing. misusing this flag can result in really slow builds.
|
||||
// Some example scenarios where you might want to use this:
|
||||
// * You're on linux/amd64 and you're building a docker image for linux/armv7 or linux/arm64
|
||||
// * You're on linux/arm64 and you're building a package for linux/arm64
|
||||
Platform dagger.Platform
|
||||
|
||||
// Context is available for all sub-commands that define their own flags.
|
||||
Context cliutil.CLIContext
|
||||
|
||||
// GrafanaOpts will be populated if the GrafanaFlags are enabled on the current sub-command.
|
||||
// GrafanaOpts *containers.GrafanaOpts
|
||||
|
||||
// PackageOpts will be populated if the PackageFlags are enabled on the current sub-command.
|
||||
// PackageOpts *containers.PackageOpts
|
||||
|
||||
// PublishOpts will be populated if the PublishFlags flags are enabled on the current sub-command
|
||||
// This is set for pipelines that publish artifacts.
|
||||
PublishOpts *containers.PublishOpts
|
||||
|
||||
// PackageInputOpts will be populated if the PackageInputFlags are enabled on current sub-command.
|
||||
// This is set for pipelines that accept a package as input.
|
||||
PackageInputOpts *containers.PackageInputOpts
|
||||
GPGOpts *gpg.GPGOpts
|
||||
DockerOpts *docker.DockerOpts
|
||||
GCPOpts *containers.GCPOpts
|
||||
ConcurrencyOpts *ConcurrencyOpts
|
||||
|
||||
// ProImageOpts will be populated if ProImageFlags are enabled on the current sub-command.
|
||||
ProImageOpts *containers.ProImageOpts
|
||||
|
||||
// NPMOpts will be populated if NPMFlags are enabled on the current sub-command.
|
||||
NpmToken string
|
||||
NpmRegistry string
|
||||
NpmTags []string
|
||||
|
||||
// GCOMOpts will be populated if GCOMFlags are enabled on the current sub-command.
|
||||
GCOMOpts *gcom.GCOMOpts
|
||||
}
|
||||
|
||||
// PipelineArgsFromContext populates a pipelines.PipelineArgs from a CLI context.
|
||||
func PipelineArgsFromContext(ctx context.Context, c cliutil.CLIContext) (PipelineArgs, error) {
|
||||
// Global flags
|
||||
var (
|
||||
verbose = c.Bool("v")
|
||||
platform = c.String("platform")
|
||||
)
|
||||
// grafanaOpts, err := containers.GrafanaOptsFromFlags(ctx, c)
|
||||
// if err != nil {
|
||||
// return PipelineArgs{}, err
|
||||
// }
|
||||
gcomOpts, err := gcom.GCOMOptsFromFlags(c)
|
||||
if err != nil {
|
||||
return PipelineArgs{}, err
|
||||
}
|
||||
|
||||
return PipelineArgs{
|
||||
Context: c,
|
||||
Verbose: verbose,
|
||||
Platform: dagger.Platform(platform),
|
||||
// GrafanaOpts: grafanaOpts,
|
||||
GPGOpts: &gpg.GPGOpts{},
|
||||
// PackageOpts: containers.PackageOptsFromFlags(c),
|
||||
PublishOpts: containers.PublishOptsFromFlags(c),
|
||||
PackageInputOpts: containers.PackageInputOptsFromFlags(c),
|
||||
DockerOpts: DockerOptsFromFlags(c),
|
||||
GCPOpts: containers.GCPOptsFromFlags(c),
|
||||
ConcurrencyOpts: ConcurrencyOptsFromFlags(c),
|
||||
ProImageOpts: containers.ProImageOptsFromFlags(c),
|
||||
GCOMOpts: gcomOpts,
|
||||
NpmToken: c.String("token"),
|
||||
NpmRegistry: c.String("registry"),
|
||||
NpmTags: c.StringSlice("tag"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// InjectPipelineArgsIntoSpan is used to copy some of the arguments passed to
|
||||
// the pipeline into a top-level OpenTelemtry span. Fields that might contain
|
||||
// secrets are left out.
|
||||
func InjectPipelineArgsIntoSpan(span trace.Span, args PipelineArgs) {
|
||||
attributes := make([]attribute.KeyValue, 0, 10)
|
||||
attributes = append(attributes, attribute.String("platform", string(args.Platform)))
|
||||
// if args.GrafanaOpts != nil {
|
||||
// attributes = append(attributes, attribute.String("go-version", args.GrafanaOpts.GoVersion))
|
||||
// attributes = append(attributes, attribute.String("version", args.GrafanaOpts.Version))
|
||||
// attributes = append(attributes, attribute.String("grafana-dir", args.GrafanaOpts.GrafanaDir))
|
||||
// attributes = append(attributes, attribute.String("grafana-ref", args.GrafanaOpts.GrafanaRef))
|
||||
// attributes = append(attributes, attribute.String("enterprise-dir", args.GrafanaOpts.EnterpriseDir))
|
||||
// attributes = append(attributes, attribute.String("enterprise-ref", args.GrafanaOpts.EnterpriseRef))
|
||||
// }
|
||||
// if args.PackageOpts != nil {
|
||||
// distros := []string{}
|
||||
// for _, distro := range args.PackageOpts.Distros {
|
||||
// distros = append(distros, string(distro))
|
||||
// }
|
||||
// attributes = append(attributes, attribute.StringSlice("package-distros", distros))
|
||||
// }
|
||||
span.SetAttributes(attributes...)
|
||||
}
|
|
@ -1,157 +0,0 @@
|
|||
package pipelines_test
|
||||
|
||||
// type TestCLIContext struct {
|
||||
// Data map[string]interface{}
|
||||
// }
|
||||
//
|
||||
// func (t *TestCLIContext) Bool(key string) bool {
|
||||
// if _, ok := t.Data[key]; !ok {
|
||||
// return false
|
||||
// }
|
||||
//
|
||||
// return t.Data[key].(bool)
|
||||
// }
|
||||
//
|
||||
// func (t *TestCLIContext) String(key string) string {
|
||||
// if _, ok := t.Data[key]; !ok {
|
||||
// return ""
|
||||
// }
|
||||
//
|
||||
// return t.Data[key].(string)
|
||||
// }
|
||||
//
|
||||
// func (t *TestCLIContext) Set(key string, val string) error {
|
||||
// t.Data[key] = val
|
||||
//
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// func (t *TestCLIContext) StringSlice(key string) []string {
|
||||
// if _, ok := t.Data[key]; !ok {
|
||||
// return nil
|
||||
// }
|
||||
// return t.Data[key].([]string)
|
||||
// }
|
||||
//
|
||||
// func (t *TestCLIContext) Path(key string) string {
|
||||
// return t.Data[key].(string)
|
||||
// }
|
||||
//
|
||||
// func (t *TestCLIContext) Int64(key string) int64 {
|
||||
// if _, ok := t.Data[key]; !ok {
|
||||
// return 0
|
||||
// }
|
||||
//
|
||||
// return t.Data[key].(int64)
|
||||
// }
|
||||
//
|
||||
// func TestPipelineArgsFromContext(t *testing.T) {
|
||||
// enterpriseDir, err := os.MkdirTemp("", "grafana-enterprise-*")
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
//
|
||||
// validData := map[string]interface{}{
|
||||
// "v": true,
|
||||
// "version": "v1.0.0",
|
||||
// "grafana": true,
|
||||
// "grafana-dir": "/grafana",
|
||||
// "grafana-ref": "asdf",
|
||||
// "enterprise": true,
|
||||
// "enterprise-dir": enterpriseDir,
|
||||
// "enterprise-ref": "1234",
|
||||
// "build-id": "build-1234",
|
||||
// "github-token": "",
|
||||
// "sign": false,
|
||||
// }
|
||||
//
|
||||
// // t.Run("It should return a PipelineArgs object if there are no errors", func(t *testing.T) {
|
||||
// // args, err := pipelines.PipelineArgsFromContext(context.Background(), &TestCLIContext{
|
||||
// // Data: validData,
|
||||
// // })
|
||||
// // if err != nil {
|
||||
// // t.Fatal(err)
|
||||
// // }
|
||||
//
|
||||
// // if args.Verbose != true {
|
||||
// // t.Error("args.Verbose should be true")
|
||||
// // }
|
||||
// // // opts := args.GrafanaOpts
|
||||
// // // if opts.Version != "v1.0.0" {
|
||||
// // // t.Error("args.Version should be v1.0.0")
|
||||
// // // }
|
||||
//
|
||||
// // if opts.BuildGrafana != true {
|
||||
// // t.Error("args.BuildGrafana should be true")
|
||||
// // }
|
||||
//
|
||||
// // if opts.GrafanaDir != "/grafana" {
|
||||
// // t.Error("args.GrafanaDir should be /grafana")
|
||||
// // }
|
||||
//
|
||||
// // if opts.GrafanaRef != "asdf" {
|
||||
// // t.Error("args.GrafanaRef should be asdf")
|
||||
// // }
|
||||
//
|
||||
// // if opts.BuildEnterprise != true {
|
||||
// // t.Error("args.Enterprise should be true")
|
||||
// // }
|
||||
//
|
||||
// // if opts.EnterpriseDir != enterpriseDir {
|
||||
// // t.Errorf("args.EnterpriseDir should be %s", enterpriseDir)
|
||||
// // }
|
||||
//
|
||||
// // if opts.EnterpriseRef != "1234" {
|
||||
// // t.Error("args.EnterpriseRef should be 1234")
|
||||
// // }
|
||||
// // })
|
||||
//
|
||||
// // t.Run("If no build ID is provided, a random 12-character string should be given", func(t *testing.T) {
|
||||
// // data := validData
|
||||
// // data["build-id"] = ""
|
||||
// // args, err := pipelines.PipelineArgsFromContext(context.Background(), &TestCLIContext{
|
||||
// // Data: data,
|
||||
// // })
|
||||
// // if err != nil {
|
||||
// // t.Fatal(err)
|
||||
// // }
|
||||
// // opts := args.GrafanaOpts
|
||||
// // if opts.BuildID == "" {
|
||||
// // t.Fatal("BuildID should not be empty")
|
||||
// // }
|
||||
// // if len(opts.BuildID) != 12 {
|
||||
// // t.Fatal("BuildID should be a 12-character string")
|
||||
// // }
|
||||
// // })
|
||||
//
|
||||
// // t.Run("If the --enterprise-ref is set to a non-default value, it should set the enterprise flag to true", func(t *testing.T) {
|
||||
// // data := validData
|
||||
// // data["enterprise"] = false
|
||||
// // data["enterprise-ref"] = "ref-1234"
|
||||
//
|
||||
// // args, err := pipelines.PipelineArgsFromContext(context.Background(), &TestCLIContext{
|
||||
// // Data: data,
|
||||
// // })
|
||||
// // if err != nil {
|
||||
// // t.Fatal(err)
|
||||
// // }
|
||||
// // opts := args.GrafanaOpts
|
||||
// // if opts.BuildEnterprise != true {
|
||||
// // t.Fatal("args.BuildEnterprise should be true")
|
||||
// // }
|
||||
// // })
|
||||
//
|
||||
// t.Run("If the --enterprise-ref is set to a non-default value, it should set the enterprise flag to true", func(t *testing.T) {
|
||||
// data := validData
|
||||
// data["enterprise"] = false
|
||||
// data["enterprise-ref"] = ""
|
||||
// data["enterprise-dir"] = filepath.Join(enterpriseDir, "does-not-exist")
|
||||
//
|
||||
// _, err := pipelines.PipelineArgsFromContext(context.Background(), &TestCLIContext{
|
||||
// Data: data,
|
||||
// })
|
||||
// if err == nil {
|
||||
// t.Fatal("error should not be empty")
|
||||
// }
|
||||
// })
|
||||
// }
|
|
@ -1,85 +0,0 @@
|
|||
package pipelines
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"dagger.io/dagger"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/containers"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/git"
|
||||
)
|
||||
|
||||
func ProImage(ctx context.Context, dc *dagger.Client, args PipelineArgs) error {
|
||||
if len(args.PackageInputOpts.Packages) > 1 {
|
||||
return fmt.Errorf("only one package is allowed: packages=%+v", args.PackageInputOpts.Packages)
|
||||
}
|
||||
packages, err := containers.GetPackages(ctx, dc, args.PackageInputOpts, args.GCPOpts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting packages: packages=%+v %w", args.PackageInputOpts.Packages, err)
|
||||
}
|
||||
|
||||
debianPackageFile := packages[0]
|
||||
|
||||
log.Printf("Cloning hosted Grafana...")
|
||||
hostedGrafanaRepo, err := git.CloneWithGitHubToken(dc, args.ProImageOpts.GitHubToken, "https://github.com/grafana/hosted-grafana.git", "main")
|
||||
if err != nil {
|
||||
return fmt.Errorf("cloning hosted-grafana repo: %w", err)
|
||||
}
|
||||
|
||||
socketPath := "/var/run/docker.sock"
|
||||
socket := dc.Host().UnixSocket(socketPath)
|
||||
|
||||
hostedGrafanaImage := fmt.Sprintf("%s/%s:%s", args.ProImageOpts.ContainerRegistry, args.ProImageOpts.Repo, args.ProImageOpts.ImageTag)
|
||||
|
||||
log.Printf("Building hosted Grafana image: %s", hostedGrafanaImage)
|
||||
container := dc.Container().From("google/cloud-sdk:433.0.0-alpine").
|
||||
WithExec([]string{
|
||||
"/bin/sh", "-c",
|
||||
"gcloud auth configure-docker --quiet",
|
||||
}).
|
||||
WithUnixSocket(socketPath, socket).
|
||||
WithDirectory("/src", hostedGrafanaRepo).
|
||||
WithFile("/src/grafana.deb", debianPackageFile).
|
||||
WithWorkdir("/src").
|
||||
WithExec([]string{
|
||||
"/bin/sh", "-c",
|
||||
"docker build --platform=linux/amd64 . -f ./cmd/hgrun/Dockerfile -t hgrun:latest",
|
||||
}).
|
||||
WithExec([]string{
|
||||
"/bin/sh", "-c",
|
||||
fmt.Sprintf("docker build --platform=linux/amd64 --build-arg=RELEASE_TYPE=%s --build-arg=GRAFANA_VERSION=%s --build-arg=HGRUN_IMAGE=hgrun:latest . -f ./docker/hosted-grafana-all/Dockerfile -t %s",
|
||||
args.ProImageOpts.ReleaseType,
|
||||
args.ProImageOpts.GrafanaVersion,
|
||||
hostedGrafanaImage,
|
||||
),
|
||||
})
|
||||
|
||||
if args.ProImageOpts.Push {
|
||||
if args.ProImageOpts.ContainerRegistry == "" {
|
||||
return fmt.Errorf("--registry=<string> is required")
|
||||
}
|
||||
|
||||
authenticator := containers.GCSAuth(dc, &containers.GCPOpts{
|
||||
ServiceAccountKey: args.GCPOpts.ServiceAccountKey,
|
||||
ServiceAccountKeyBase64: args.GCPOpts.ServiceAccountKeyBase64,
|
||||
})
|
||||
|
||||
authenticatedContainer, err := authenticator.Authenticate(dc, container)
|
||||
if err != nil {
|
||||
return fmt.Errorf("authenticating container with gcs auth: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("Pushing hosted Grafana image to registry...")
|
||||
container = authenticatedContainer.WithExec([]string{
|
||||
"/bin/sh", "-c",
|
||||
fmt.Sprintf("docker push %s", hostedGrafanaImage),
|
||||
})
|
||||
}
|
||||
|
||||
if _, err := containers.ExitError(ctx, container); err != nil {
|
||||
return fmt.Errorf("container did not exit successfully: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package pipelines
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type SyncWriter struct {
|
||||
Writer io.Writer
|
||||
|
||||
mutex *sync.Mutex
|
||||
}
|
||||
|
||||
func NewSyncWriter(w io.Writer) *SyncWriter {
|
||||
return &SyncWriter{
|
||||
Writer: w,
|
||||
mutex: &sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SyncWriter) Write(b []byte) (int, error) {
|
||||
w.mutex.Lock()
|
||||
defer w.mutex.Unlock()
|
||||
|
||||
return w.Writer.Write(b)
|
||||
}
|
||||
|
||||
var Stdout = NewSyncWriter(os.Stdout)
|
|
@ -1,38 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
local_dst="dist/${DRONE_BUILD_EVENT}"
|
||||
set -e
|
||||
|
||||
docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
|
||||
# This command enables qemu emulators for building Docker images for arm64/armv6/armv7/etc on the host.
|
||||
docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
|
||||
|
||||
dagger run --silent go run ./pkg/build/cmd \
|
||||
artifacts \
|
||||
-a targz:grafana:linux/amd64 \
|
||||
-a targz:grafana:linux/arm64 \
|
||||
-a targz:grafana:linux/arm/v6 \
|
||||
-a targz:grafana:linux/arm/v7 \
|
||||
-a targz:grafana:windows/amd64 \
|
||||
-a targz:grafana:darwin/amd64 \
|
||||
-a deb:grafana:linux/amd64 \
|
||||
-a deb:grafana:linux/arm64 \
|
||||
-a deb:grafana:linux/arm/v6 \
|
||||
-a deb:grafana:linux/arm/v7 \
|
||||
-a docker:grafana:linux/amd64 \
|
||||
-a docker:grafana:linux/arm64 \
|
||||
-a docker:grafana:linux/arm/v7 \
|
||||
--yarn-cache=${YARN_CACHE_FOLDER} \
|
||||
--checksum \
|
||||
--build-id=${DRONE_BUILD_NUMBER} \
|
||||
--grafana-dir=${GRAFANA_DIR} \
|
||||
--github-token=${GITHUB_TOKEN} \
|
||||
--ubuntu-base=${UBUNTU_BASE} \
|
||||
--alpine-base=${ALPINE_BASE} \
|
||||
--destination=${local_dst} > assets.txt
|
||||
|
||||
echo "Final list of artifacts:"
|
||||
cat assets.txt
|
||||
|
||||
# Move the tar.gz packages to their expected locations
|
||||
cat assets.txt | IS_MAIN=true go run ./pkg/build/daggerbuild/scripts/move_packages.go ./dist/main
|
|
@ -1,37 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
local_dst="dist/${DRONE_BUILD_EVENT}"
|
||||
set -e
|
||||
|
||||
docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
|
||||
# This command enables qemu emulators for building Docker images for arm64/armv6/armv7/etc on the host.
|
||||
docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
|
||||
dagger run --silent go run ./pkg/build/cmd \
|
||||
artifacts \
|
||||
-a targz:enterprise:linux/amd64 \
|
||||
-a targz:enterprise:linux/arm64 \
|
||||
-a targz:enterprise:linux/arm/v6 \
|
||||
-a targz:enterprise:linux/arm/v7 \
|
||||
-a deb:enterprise:linux/amd64 \
|
||||
-a deb:enterprise:linux/arm64 \
|
||||
-a deb:enterprise:linux/arm/v6 \
|
||||
-a deb:enterprise:linux/arm/v7 \
|
||||
-a docker:enterprise:linux/amd64 \
|
||||
-a docker:enterprise:linux/arm64 \
|
||||
--yarn-cache=${YARN_CACHE_FOLDER} \
|
||||
--checksum \
|
||||
--verify \
|
||||
--build-id=${DRONE_BUILD_NUMBER} \
|
||||
--grafana-ref=${SOURCE_COMMIT} \
|
||||
--grafana-repo="https://github.com/grafana/grafana.git" \
|
||||
--enterprise-ref=${DRONE_COMMIT} \
|
||||
--github-token=${GITHUB_TOKEN} \
|
||||
--ubuntu-base=${UBUNTU_BASE} \
|
||||
--alpine-base=${ALPINE_BASE} \
|
||||
--patches-repo=${PATCHES_REPO} \
|
||||
--patches-path=${PATCHES_PATH} \
|
||||
--destination=${local_dst} > assets.txt
|
||||
|
||||
cat assets.txt
|
||||
|
||||
# Move the tar.gz packages to their expected locations
|
||||
cat assets.txt | DESTINATION=gs://grafana-downloads IS_MAIN=true go run ./pkg/build/daggerbuild/scripts/move_packages.go ./dist/main
|
|
@ -1,32 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
local_dst="./dist/${DRONE_BUILD_EVENT}"
|
||||
set -e
|
||||
|
||||
docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
|
||||
# This command enables qemu emulators for building Docker images for arm64/armv6/armv7/etc on the host.
|
||||
docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
|
||||
# Build all of the grafana.tar.gz packages.
|
||||
dagger run --silent go run ./pkg/build/cmd \
|
||||
artifacts \
|
||||
-a targz:pro:linux/amd64 \
|
||||
-a targz:pro:linux/arm64 \
|
||||
-a deb:pro:linux/amd64 \
|
||||
-a deb:pro:linux/arm64 \
|
||||
-a frontend:enterprise \
|
||||
--yarn-cache=${YARN_CACHE_FOLDER} \
|
||||
--checksum \
|
||||
--build-id=${DRONE_BUILD_NUMBER} \
|
||||
--grafana-ref=${SOURCE_COMMIT} \
|
||||
--grafana-repo="https://github.com/grafana/grafana.git" \
|
||||
--enterprise-ref=${DRONE_COMMIT} \
|
||||
--github-token=${GITHUB_TOKEN} \
|
||||
--ubuntu-base=${UBUNTU_BASE} \
|
||||
--alpine-base=${ALPINE_BASE} \
|
||||
--patches-repo=${PATCHES_REPO} \
|
||||
--patches-path=${PATCHES_PATH} \
|
||||
--destination=${local_dst} > assets.txt
|
||||
|
||||
echo "Final list of artifacts:"
|
||||
# Move the tar.gz packages to their expected locations
|
||||
cat assets.txt | grep -v "public" | DESTINATION=gs://grafana-downloads-enterprise2 IS_MAIN=true go run ./pkg/build/daggerbuild/scripts/move_packages.go ./dist/main
|
||||
cat assets.txt | grep "public" | DESTINATION=gs://grafana-static-assets IS_MAIN=true go run ./pkg/build/daggerbuild/scripts/move_packages.go ./dist/cdn
|
|
@ -1,52 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
set -e
|
||||
local_dst="${DRONE_WORKSPACE}/dist"
|
||||
|
||||
docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
|
||||
# This command enables qemu emulators for building Docker images for arm64/armv6/armv7/etc on the host.
|
||||
docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
|
||||
|
||||
# -a targz:enterprise:linux/arm/v6 \
|
||||
# -a targz:enterprise:linux/arm/v7 \
|
||||
# -a deb:enterprise:linux/arm/v6:nightly \
|
||||
# -a deb:enterprise:linux/arm/v7:nightly \
|
||||
# -a docker:enterprise:linux/arm/v7 \
|
||||
# -a docker:enterprise:linux/arm/v7:ubuntu \
|
||||
|
||||
dagger run --silent go run ./pkg/build/cmd \
|
||||
artifacts \
|
||||
-a targz:enterprise:linux/amd64 \
|
||||
-a targz:enterprise:linux/arm64 \
|
||||
-a targz:enterprise:linux/arm/v7 \
|
||||
-a targz:enterprise:linux/arm/v6 \
|
||||
-a deb:enterprise:linux/amd64:nightly \
|
||||
-a deb:enterprise:linux/arm64:nightly \
|
||||
-a deb:enterprise:linux/arm/v6:nightly \
|
||||
-a deb:enterprise:linux/arm/v7:nightly \
|
||||
-a rpm:enterprise:linux/amd64:sign:nightly \
|
||||
-a rpm:enterprise:linux/arm64:sign:nightly \
|
||||
-a targz:enterprise:windows/amd64 \
|
||||
-a targz:enterprise:windows/arm64 \
|
||||
-a targz:enterprise:darwin/amd64 \
|
||||
-a targz:enterprise:darwin/arm64 \
|
||||
-a zip:enterprise:windows/amd64 \
|
||||
-a msi:enterprise:windows/amd64 \
|
||||
-a docker:enterprise:linux/amd64 \
|
||||
-a docker:enterprise:linux/arm64 \
|
||||
-a docker:enterprise:linux/arm/v7 \
|
||||
-a docker:enterprise:linux/amd64:ubuntu \
|
||||
-a docker:enterprise:linux/arm64:ubuntu \
|
||||
-a docker:enterprise:linux/arm/v7:ubuntu \
|
||||
--checksum \
|
||||
--verify=false \
|
||||
--build-id=${DRONE_BUILD_NUMBER} \
|
||||
--grafana-ref=main \
|
||||
--enterprise-ref=main \
|
||||
--grafana-repo=https://github.com/grafana/grafana.git \
|
||||
--github-token=${GITHUB_TOKEN} \
|
||||
--destination=${local_dst} \
|
||||
--yarn-cache=${YARN_CACHE_FOLDER} \
|
||||
--ubuntu-base="${UBUNTU_BASE}" \
|
||||
--alpine-base="${ALPINE_BASE}" > assets.txt
|
||||
|
||||
cat assets.txt
|
|
@ -1,43 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
set -e
|
||||
local_dst="${DRONE_WORKSPACE}/dist"
|
||||
|
||||
docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
|
||||
# This command enables qemu emulators for building Docker images for arm64/armv6/armv7/etc on the host.
|
||||
docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
|
||||
|
||||
dagger run --silent go run ./pkg/build/cmd \
|
||||
artifacts \
|
||||
-a targz:grafana:linux/amd64 \
|
||||
-a targz:grafana:linux/arm64 \
|
||||
-a targz:grafana:linux/arm/v7 \
|
||||
-a targz:grafana:linux/arm/v6 \
|
||||
-a deb:grafana:linux/amd64:nightly \
|
||||
-a deb:grafana:linux/arm64:nightly \
|
||||
-a deb:grafana:linux/arm/v6:nightly \
|
||||
-a deb:grafana:linux/arm/v7:nightly \
|
||||
-a rpm:grafana:linux/amd64:sign:nightly \
|
||||
-a rpm:grafana:linux/arm64:sign:nightly \
|
||||
-a targz:grafana:windows/amd64 \
|
||||
-a targz:grafana:windows/arm64 \
|
||||
-a targz:grafana:darwin/amd64 \
|
||||
-a targz:grafana:darwin/arm64 \
|
||||
-a zip:grafana:windows/amd64 \
|
||||
-a msi:grafana:windows/amd64 \
|
||||
-a docker:grafana:linux/amd64 \
|
||||
-a docker:grafana:linux/arm64 \
|
||||
-a docker:grafana:linux/arm/v7 \
|
||||
-a docker:grafana:linux/amd64:ubuntu \
|
||||
-a docker:grafana:linux/arm64:ubuntu \
|
||||
-a docker:grafana:linux/arm/v7:ubuntu \
|
||||
--checksum \
|
||||
--verify \
|
||||
--build-id=${DRONE_BUILD_NUMBER} \
|
||||
--grafana-dir=${GRAFANA_DIR} \
|
||||
--github-token=${GITHUB_TOKEN} \
|
||||
--destination=${local_dst} \
|
||||
--yarn-cache=${YARN_CACHE_FOLDER} \
|
||||
--ubuntu-base="${UBUNTU_BASE}" \
|
||||
--alpine-base="${ALPINE_BASE}" > assets.txt
|
||||
|
||||
cat assets.txt
|
|
@ -1,51 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
local_dst="dist/${DRONE_BUILD_EVENT}"
|
||||
set -e
|
||||
|
||||
docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
|
||||
# This command enables qemu emulators for building Docker images for arm64/armv6/armv7/etc on the host.
|
||||
docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
|
||||
|
||||
# Build all of the grafana.tar.gz packages.
|
||||
dagger run --silent go run ./pkg/build/cmd \
|
||||
artifacts \
|
||||
-a targz:enterprise:linux/amd64 \
|
||||
-a targz:enterprise:linux/arm64 \
|
||||
-a targz:enterprise:linux/arm/v6 \
|
||||
-a targz:enterprise:linux/arm/v7 \
|
||||
-a deb:enterprise:linux/amd64 \
|
||||
-a deb:enterprise:linux/arm64 \
|
||||
-a deb:enterprise:linux/arm/v6 \
|
||||
-a deb:enterprise:linux/arm/v7 \
|
||||
-a rpm:enterprise:linux/amd64:sign \
|
||||
-a rpm:enterprise:linux/arm64:sign \
|
||||
-a targz:enterprise:windows/amd64 \
|
||||
-a targz:enterprise:windows/arm64 \
|
||||
-a targz:enterprise:darwin/amd64 \
|
||||
-a targz:enterprise:darwin/arm64 \
|
||||
-a targz:boring:linux/amd64/dynamic \
|
||||
-a zip:enterprise:windows/amd64 \
|
||||
-a msi:enterprise:windows/amd64 \
|
||||
-a docker:enterprise:linux/amd64 \
|
||||
-a docker:enterprise:linux/arm64 \
|
||||
-a docker:enterprise:linux/arm/v7 \
|
||||
-a docker:enterprise:linux/amd64:ubuntu \
|
||||
-a docker:enterprise:linux/arm64:ubuntu \
|
||||
-a docker:enterprise:linux/arm/v7:ubuntu \
|
||||
-a docker:boring:linux/amd64/dynamic \
|
||||
--yarn-cache=${YARN_CACHE_FOLDER} \
|
||||
--verify \
|
||||
--checksum \
|
||||
--parallel=5 \
|
||||
--build-id=${DRONE_BUILD_NUMBER} \
|
||||
--enterprise-ref=${DRONE_TAG} \
|
||||
--grafana-ref=${DRONE_TAG} \
|
||||
--grafana-repo=https://github.com/grafana/grafana-security-mirror.git \
|
||||
--github-token=${GITHUB_TOKEN} \
|
||||
--ubuntu-base="${UBUNTU_BASE}" \
|
||||
--alpine-base="${ALPINE_BASE}" \
|
||||
--version=${DRONE_TAG} \
|
||||
--destination=${local_dst} > assets.txt
|
||||
|
||||
# Move the tar.gz packages to their expected locations
|
||||
cat assets.txt | go run ./pkg/build/daggerbuild/scripts/move_packages.go ./dist/prerelease
|
|
@ -1,47 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
dst="${DESTINATION}/${DRONE_BUILD_EVENT}"
|
||||
local_dst="file://dist/${DRONE_BUILD_EVENT}"
|
||||
set -e
|
||||
|
||||
docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
|
||||
# This command enables qemu emulators for building Docker images for arm64/armv6/armv7/etc on the host.
|
||||
docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
|
||||
|
||||
dagger run --silent go run ./pkg/build/cmd \
|
||||
artifacts \
|
||||
-a npm:grafana \
|
||||
-a storybook \
|
||||
-a targz:grafana:linux/amd64 \
|
||||
-a targz:grafana:linux/arm64 \
|
||||
-a targz:grafana:linux/arm/v6 \
|
||||
-a targz:grafana:linux/arm/v7 \
|
||||
-a deb:grafana:linux/amd64 \
|
||||
-a deb:grafana:linux/arm64 \
|
||||
-a deb:grafana:linux/arm/v6 \
|
||||
-a deb:grafana:linux/arm/v7 \
|
||||
-a rpm:grafana:linux/amd64:sign \
|
||||
-a rpm:grafana:linux/arm64:sign \
|
||||
-a docker:grafana:linux/amd64 \
|
||||
-a docker:grafana:linux/arm64 \
|
||||
-a docker:grafana:linux/arm/v7 \
|
||||
-a docker:grafana:linux/amd64:ubuntu \
|
||||
-a docker:grafana:linux/arm64:ubuntu \
|
||||
-a docker:grafana:linux/arm/v7:ubuntu \
|
||||
-a targz:grafana:windows/amd64 \
|
||||
-a targz:grafana:windows/arm64 \
|
||||
-a targz:grafana:darwin/amd64 \
|
||||
-a targz:grafana:darwin/arm64 \
|
||||
-a zip:grafana:windows/amd64 \
|
||||
-a msi:grafana:windows/amd64 \
|
||||
--yarn-cache=${YARN_CACHE_FOLDER} \
|
||||
--checksum \
|
||||
--verify \
|
||||
--build-id=${DRONE_BUILD_NUMBER} \
|
||||
--grafana-dir=${GRAFANA_DIR} \
|
||||
--github-token=${GITHUB_TOKEN} \
|
||||
--ubuntu-base="${UBUNTU_BASE}" \
|
||||
--alpine-base="${ALPINE_BASE}" \
|
||||
--version=${DRONE_TAG} \
|
||||
--destination=${local_dst} > assets.txt
|
||||
|
||||
cat assets.txt | go run ./pkg/build/daggerbuild/scripts/move_packages.go ./dist/prerelease
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue