Skip to content

Commit c10d5d9

Browse files
committed
Adds Drone and Github workflow for Grafana's fork
This commit adds the files that are specific to Grafana's fork that are not intended to be included in the upstream. This files are already present in the commit history (they were deleted), but this is an attempt of a fresh start on top of the upstream's `main`. At the moment, this should the only commit we expect to skip when sending our changes.
1 parent b2707b1 commit c10d5d9

File tree

15 files changed

+700
-0
lines changed

15 files changed

+700
-0
lines changed

.drone/Tests.Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
FROM golang:alpine as builder
2+
RUN apk --no-cache add make gcc git cairo-dev musl-dev

.drone/cmd/coverage/main.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"flag"
6+
"fmt"
7+
"os"
8+
"sort"
9+
"strconv"
10+
"strings"
11+
)
12+
13+
type aggregation struct {
14+
NumStmts int
15+
NumCoveredStmts int
16+
}
17+
18+
func (a *aggregation) CoveragePct() string {
19+
pct := (float64(a.NumCoveredStmts) / float64(a.NumStmts)) * 100
20+
return fmt.Sprintf("%.1f%%", pct)
21+
}
22+
23+
func main() {
24+
covFilename := flag.String("f", "coverage.out", "Output of `go test -coverprofile=coverage.out ./...`")
25+
flag.Parse()
26+
27+
f, err := os.Open(*covFilename)
28+
if err != nil {
29+
panic(err)
30+
}
31+
32+
agg := make(map[string]*aggregation)
33+
34+
s := bufio.NewScanner(f)
35+
s.Split(bufio.ScanLines)
36+
37+
s.Scan() // First line specifies the mode; it doesn't affect what we do so we can just skip it.
38+
39+
for s.Scan() {
40+
line := s.Text()
41+
42+
cols := strings.Fields(line)
43+
key := strings.Split(cols[0], ":")[0]
44+
45+
numStmts, err := strconv.Atoi(cols[1])
46+
if err != nil {
47+
panic(err)
48+
}
49+
numTimesCovered, err := strconv.Atoi(cols[2])
50+
if err != nil {
51+
panic(err)
52+
}
53+
54+
if val, ok := agg[key]; ok {
55+
val.NumStmts += numStmts
56+
if numTimesCovered > 0 {
57+
val.NumCoveredStmts += numStmts
58+
}
59+
} else {
60+
numCoveredStmts := 0
61+
if numTimesCovered > 0 {
62+
numCoveredStmts = numStmts
63+
}
64+
65+
agg[key] = &aggregation{
66+
NumStmts: numStmts,
67+
NumCoveredStmts: numCoveredStmts,
68+
}
69+
}
70+
}
71+
72+
keys := make([]string, 0, len(agg))
73+
for k := range agg {
74+
keys = append(keys, k)
75+
}
76+
sort.Strings(keys)
77+
78+
fmt.Println("Go coverage report:")
79+
fmt.Println("<details>")
80+
fmt.Println("<summary>Click to expand.</summary>")
81+
fmt.Println("")
82+
fmt.Println("| File | % |")
83+
fmt.Println("| ---- | - |")
84+
85+
totalStmts := 0
86+
totalCoveredStmts := 0
87+
88+
for _, k := range keys {
89+
a := agg[k]
90+
fmt.Printf("| %s | %s |\n", k, a.CoveragePct())
91+
92+
totalStmts += a.NumStmts
93+
totalCoveredStmts += a.NumCoveredStmts
94+
}
95+
96+
fmt.Printf("| total | %.1f%% |\n", (float64(totalCoveredStmts)/float64(totalStmts))*100)
97+
fmt.Println("</details>")
98+
}

.drone/cmd/ghcomment/main.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"flag"
6+
"io/ioutil"
7+
"os"
8+
"strconv"
9+
"strings"
10+
11+
"github.com/shurcooL/githubv4"
12+
13+
"github.com/go-graphite/carbonapi/drone/pkg/github"
14+
)
15+
16+
const CommenterLogin = "grafanabot"
17+
18+
func main() {
19+
grafanabotPat := getRequiredEnv("GRAFANABOT_PAT")
20+
21+
repoOwner := getRequiredEnv("DRONE_REPO_OWNER")
22+
repoName := getRequiredEnv("DRONE_REPO_NAME")
23+
24+
pullRequest, err := strconv.Atoi(getRequiredEnv("DRONE_PULL_REQUEST"))
25+
if err != nil {
26+
panic(err)
27+
}
28+
29+
commentTypeIdentifier := flag.String("id", "", "String that identifies the comment type being submitted")
30+
commentBodyFilename := flag.String("bodyfile", "", "A file containing the comment body")
31+
flag.Parse()
32+
33+
if *commentTypeIdentifier == "" {
34+
panic("Required argument: -i")
35+
}
36+
if *commentBodyFilename == "" {
37+
panic("Required argument: -b")
38+
}
39+
40+
api := github.NewAPI(context.Background(), grafanabotPat)
41+
42+
err = minimizeOutdatedComments(api, repoOwner, repoName, pullRequest, *commentTypeIdentifier)
43+
if err != nil {
44+
panic(err)
45+
}
46+
47+
commentBody, err := ioutil.ReadFile(*commentBodyFilename)
48+
if err != nil {
49+
panic(err)
50+
}
51+
52+
err = addComment(api, repoOwner, repoName, pullRequest, string(commentBody))
53+
if err != nil {
54+
panic(err)
55+
}
56+
}
57+
58+
func getRequiredEnv(k string) string {
59+
v, p := os.LookupEnv(k)
60+
if !p {
61+
panic("Missing required env var: " + k)
62+
}
63+
64+
return v
65+
}
66+
67+
func minimizeOutdatedComments(api *github.API, repoOwner string, repoName string, pullRequestNo int, commentTypeIdentifier string) error {
68+
prComments, err := api.ListPullRequestComments(repoOwner, repoName, pullRequestNo)
69+
if err != nil {
70+
return err
71+
}
72+
73+
for _, comment := range prComments {
74+
if comment.Author.Login == CommenterLogin && strings.Contains(comment.Body, commentTypeIdentifier) && !comment.IsMinimized {
75+
err := api.MinimizeComment(comment.ID, githubv4.ReportedContentClassifiersOutdated)
76+
if err != nil {
77+
return err
78+
}
79+
}
80+
}
81+
82+
return nil
83+
}
84+
85+
func addComment(api *github.API, repoOwner string, repoName string, pullRequestNo int, commentBody string) error {
86+
pullRequestNodeID, err := api.GetPullRequestNodeID(repoOwner, repoName, pullRequestNo)
87+
if err != nil {
88+
return err
89+
}
90+
91+
_, err = api.AddComment(pullRequestNodeID, commentBody)
92+
if err != nil {
93+
return err
94+
}
95+
96+
return nil
97+
}

.drone/drone.jsonnet

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
local drone = import 'lib/drone/drone.libsonnet';
2+
local images = import 'lib/drone/images.libsonnet';
3+
local triggers = import 'lib/drone/triggers.libsonnet';
4+
local vault = import 'lib/vault/vault.libsonnet';
5+
6+
local pipeline = drone.pipeline;
7+
local step = drone.step;
8+
local withInlineStep = drone.withInlineStep;
9+
local withStep = drone.withStep;
10+
local withSteps = drone.withSteps;
11+
12+
local imagePullSecrets = { image_pull_secrets: ['dockerconfigjson'] };
13+
14+
local commentCoverageLintReport = {
15+
step: step('coverage + lint', $.commands, image=$.image, environment=$.environment),
16+
commands: [
17+
// Build drone utilities.
18+
'scripts/build-drone-utilities.sh',
19+
// Generate the raw coverage report.
20+
'go test -coverprofile=coverage.out ./...',
21+
// Process the raw coverage report.
22+
'.drone/coverage > coverage_report.out',
23+
// Generate the lint report.
24+
'scripts/generate-lint-report.sh',
25+
// Combine the reports.
26+
'cat coverage_report.out > report.out',
27+
'echo "" >> report.out',
28+
'cat lint.out >> report.out',
29+
// Submit the comment to GitHub.
30+
'.drone/ghcomment -id "Go coverage report:" -bodyfile report.out',
31+
],
32+
environment: {
33+
GRAFANABOT_PAT: { from_secret: 'gh_token' },
34+
},
35+
image: images._images.goLint,
36+
};
37+
38+
local buildAndPushImages = {
39+
// step builds the pipeline step to build and push a docker image
40+
step(app): step(
41+
'%s: build and push' % app,
42+
[],
43+
image=buildAndPushImages.pluginName,
44+
settings=buildAndPushImages.settings(app),
45+
),
46+
47+
pluginName: 'plugins/gcr',
48+
49+
// settings generates the CI Pipeline step settings
50+
settings(app): {
51+
repo: $._repo(app),
52+
registry: $._registry,
53+
dockerfile: './Dockerfile',
54+
json_key: { from_secret: 'gcr_admin' },
55+
mirror: 'https://mirror.gcr.io',
56+
build_args: ['cmd=' + app],
57+
},
58+
59+
// image generates the image for the given app
60+
image(app): $._registry + '/' + $._repo(app),
61+
62+
_repo(app):: 'kubernetes-dev/' + app,
63+
_registry:: 'us.gcr.io',
64+
};
65+
66+
local runTests = {
67+
step: step('run tests', $.commands, image=$.image),
68+
commands: [
69+
'make test'
70+
],
71+
image: images._images.testRunner,
72+
settings: {
73+
74+
}
75+
};
76+
77+
[
78+
pipeline('test')
79+
+ withStep(runTests.step)
80+
+ imagePullSecrets
81+
+ triggers.pr
82+
+ triggers.main,
83+
84+
pipeline('coverageLintReport')
85+
+ withStep(commentCoverageLintReport.step)
86+
+ triggers.pr,
87+
]
88+
+ [
89+
vault.secret('dockerconfigjson', 'secret/data/common/gcr', '.dockerconfigjson'),
90+
vault.secret('gh_token', 'infra/data/ci/github/grafanabot', 'pat'),
91+
vault.secret('gcr_admin', 'infra/data/ci/gcr-admin', 'service-account'),
92+
vault.secret('argo_token', 'infra/data/ci/argo-workflows/trigger-service-account', 'token'),
93+
]

.drone/drone.yml

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
depends_on: null
3+
image_pull_secrets:
4+
- dockerconfigjson
5+
kind: pipeline
6+
name: test
7+
steps:
8+
- commands:
9+
- make test
10+
depends_on: []
11+
entrypoint: null
12+
environment: {}
13+
image: us.gcr.io/kubernetes-dev/carbonapi/test-runner:latest
14+
name: run tests
15+
settings: {}
16+
trigger:
17+
branch:
18+
- main
19+
event:
20+
include:
21+
- pull_request
22+
- push
23+
type: docker
24+
---
25+
depends_on: null
26+
kind: pipeline
27+
name: coverageLintReport
28+
steps:
29+
- commands:
30+
- scripts/build-drone-utilities.sh
31+
- go test -coverprofile=coverage.out ./...
32+
- .drone/coverage > coverage_report.out
33+
- scripts/generate-lint-report.sh
34+
- cat coverage_report.out > report.out
35+
- echo "" >> report.out
36+
- cat lint.out >> report.out
37+
- .drone/ghcomment -id "Go coverage report:" -bodyfile report.out
38+
depends_on: []
39+
entrypoint: null
40+
environment:
41+
GRAFANABOT_PAT:
42+
from_secret: gh_token
43+
image: golangci/golangci-lint:v1.45
44+
name: coverage + lint
45+
settings: {}
46+
trigger:
47+
event:
48+
include:
49+
- pull_request
50+
type: docker
51+
---
52+
get:
53+
name: .dockerconfigjson
54+
path: secret/data/common/gcr
55+
kind: secret
56+
name: dockerconfigjson
57+
---
58+
get:
59+
name: pat
60+
path: infra/data/ci/github/grafanabot
61+
kind: secret
62+
name: gh_token
63+
---
64+
get:
65+
name: service-account
66+
path: infra/data/ci/gcr-admin
67+
kind: secret
68+
name: gcr_admin
69+
---
70+
get:
71+
name: token
72+
path: infra/data/ci/argo-workflows/trigger-service-account
73+
kind: secret
74+
name: argo_token
75+
---
76+
kind: signature
77+
hmac: 786972e7020e02e75b297bf8f7a67669cf11bd5bf02f61ac62ec63d0fca2a6c1
78+
79+
...

.drone/go.mod

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module github.com/go-graphite/carbonapi/drone
2+
3+
go 1.18
4+
5+
require (
6+
github.com/shurcooL/githubv4 v0.0.0-20220520033151-0b4e3294ff00
7+
golang.org/x/oauth2 v0.0.0-20220630143837-2104d58473e0
8+
)
9+
10+
require (
11+
github.com/golang/protobuf v1.5.2 // indirect
12+
github.com/shurcooL/graphql v0.0.0-20220606043923-3cf50f8a0a29 // indirect
13+
golang.org/x/net v0.0.0-20220706163947-c90051bbdb60 // indirect
14+
google.golang.org/appengine v1.6.7 // indirect
15+
google.golang.org/protobuf v1.28.0 // indirect
16+
)

0 commit comments

Comments
 (0)