Skip to content

Commit 69b84eb

Browse files
committed
Revert "remove githubgen tool"
This reverts commit 8032a3f.
1 parent b5cc54d commit 69b84eb

File tree

9 files changed

+669
-0
lines changed

9 files changed

+669
-0
lines changed

cmd/githubgen/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include ../../Makefile.Common

cmd/githubgen/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
⚠️ This executable has moved to [opentelemetry-go-build-tools](https://github.com/open-telemetry/opentelemetry-go-build-tools/tree/main/githubgen).
2+
3+
This code is deprecated and will be removed soon. See https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/37294.
4+
5+
# githubgen
6+
7+
This executable is used to generate the `.github/CODEOWNERS` and `.github/ALLOWLIST` files.
8+
9+
It reads status metadata from `metadata.yaml` files located throughout the repository.
10+
11+
It checks that codeowners are known members of the OpenTelemetry organization.
12+
13+
## Usage
14+
15+
```
16+
$> make gengithub
17+
```
18+
The equivalent of:
19+
```
20+
$> cd cmd/githubgen && $(GOCMD) install .
21+
$> GITHUB_TOKEN=<mypattoken> githubgen --folder . [--allowlist cmd/githubgen/allowlist.txt]
22+
```
23+
24+
## Checking codeowners against OpenTelemetry membership via Github API
25+
26+
To authenticate, set the environment variable `GITHUB_TOKEN` to a PAT token. If a PAT is not available you can use the `--skipgithub` flag to avoid checking for membership in the GitHub organization.
27+
28+
For each codeowner, the script will check if the user is registered as a member of the OpenTelemetry organization.
29+
30+
If any codeowner is missing, it will stop and print names of missing codeowners.
31+
32+
These can be added to allowlist.txt as a workaround.
33+
34+
If a codeowner is present in allowlist.txt and also a member of the OpenTelemetry organization, the script will error out.
35+

cmd/githubgen/codeowners.go

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
package main
4+
5+
import (
6+
"context"
7+
"fmt"
8+
"os"
9+
"path/filepath"
10+
"sort"
11+
"strings"
12+
13+
"github.com/google/go-github/v68/github"
14+
)
15+
16+
const allowlistHeader = `# Code generated by githubgen. DO NOT EDIT.
17+
#####################################################
18+
#
19+
# List of components in OpenTelemetry Collector Contrib
20+
# waiting on owners to be assigned
21+
#
22+
#####################################################
23+
#
24+
# Learn about membership in OpenTelemetry community:
25+
# https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md
26+
#
27+
#
28+
# Learn about CODEOWNERS file format:
29+
# https://help.github.com/en/articles/about-code-owners
30+
#
31+
32+
##
33+
# NOTE: New components MUST have one or more codeowners. Add codeowners to the component metadata.yaml and run make gengithub
34+
##
35+
36+
## COMMON & SHARED components
37+
internal/common
38+
39+
`
40+
41+
const unmaintainedHeader = `
42+
43+
## UNMAINTAINED components
44+
45+
`
46+
47+
const codeownersHeader = `# Code generated by githubgen. DO NOT EDIT.
48+
#####################################################
49+
#
50+
# List of codeowners for OpenTelemetry Collector Contrib
51+
#
52+
#####################################################
53+
#
54+
# Learn about membership in OpenTelemetry community:
55+
# https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md
56+
#
57+
#
58+
# Learn about CODEOWNERS file format:
59+
# https://help.github.com/en/articles/about-code-owners
60+
#
61+
62+
* @open-telemetry/collector-contrib-approvers
63+
`
64+
65+
const distributionCodeownersHeader = `
66+
#####################################################
67+
#
68+
# List of distribution maintainers for OpenTelemetry Collector Contrib
69+
#
70+
#####################################################
71+
`
72+
73+
type codeownersGenerator struct {
74+
skipGithub bool
75+
}
76+
77+
func (cg codeownersGenerator) generate(data *githubData) error {
78+
allowlistData, err := os.ReadFile(data.allowlistFilePath)
79+
if err != nil {
80+
return err
81+
}
82+
allowlistLines := strings.Split(string(allowlistData), "\n")
83+
84+
allowlist := make(map[string]struct{}, len(allowlistLines))
85+
unusedAllowlist := make(map[string]struct{}, len(allowlistLines))
86+
for _, line := range allowlistLines {
87+
if line == "" {
88+
continue
89+
}
90+
allowlist[line] = struct{}{}
91+
unusedAllowlist[line] = struct{}{}
92+
}
93+
var missingCodeowners []string
94+
var duplicateCodeowners []string
95+
members, err := cg.getGithubMembers()
96+
if err != nil {
97+
return err
98+
}
99+
for _, codeowner := range data.codeowners {
100+
_, present := members[codeowner]
101+
102+
if !present {
103+
_, allowed := allowlist[codeowner]
104+
delete(unusedAllowlist, codeowner)
105+
allowed = allowed || strings.HasPrefix(codeowner, "open-telemetry/")
106+
if !allowed {
107+
missingCodeowners = append(missingCodeowners, codeowner)
108+
}
109+
} else if _, ok := allowlist[codeowner]; ok {
110+
duplicateCodeowners = append(duplicateCodeowners, codeowner)
111+
}
112+
}
113+
if len(missingCodeowners) > 0 && !cg.skipGithub {
114+
sort.Strings(missingCodeowners)
115+
return fmt.Errorf("codeowners are not members: %s", strings.Join(missingCodeowners, ", "))
116+
}
117+
if len(duplicateCodeowners) > 0 {
118+
sort.Strings(duplicateCodeowners)
119+
return fmt.Errorf("codeowners members duplicate in allowlist: %s", strings.Join(duplicateCodeowners, ", "))
120+
}
121+
if len(unusedAllowlist) > 0 {
122+
var unused []string
123+
for k := range unusedAllowlist {
124+
unused = append(unused, k)
125+
}
126+
sort.Strings(unused)
127+
return fmt.Errorf("unused members in allowlist: %s", strings.Join(unused, ", "))
128+
}
129+
130+
codeowners := codeownersHeader
131+
deprecatedList := "## DEPRECATED components\n"
132+
unmaintainedList := "\n## UNMAINTAINED components\n"
133+
134+
unmaintainedCodeowners := unmaintainedHeader
135+
currentFirstSegment := ""
136+
LOOP:
137+
for _, key := range data.folders {
138+
m := data.components[key]
139+
for stability := range m.Status.Stability {
140+
if stability == unmaintainedStatus {
141+
unmaintainedList += key + "/\n"
142+
unmaintainedCodeowners += fmt.Sprintf("%s/%s @open-telemetry/collector-contrib-approvers\n", key, strings.Repeat(" ", data.maxLength-len(key)))
143+
continue LOOP
144+
}
145+
if stability == "deprecated" && (m.Status.Codeowners == nil || len(m.Status.Codeowners.Active) == 0) {
146+
deprecatedList += key + "/\n"
147+
}
148+
}
149+
150+
if m.Status.Codeowners != nil {
151+
parts := strings.Split(key, string(os.PathSeparator))
152+
firstSegment := parts[0]
153+
if firstSegment != currentFirstSegment {
154+
currentFirstSegment = firstSegment
155+
codeowners += "\n"
156+
}
157+
owners := ""
158+
for _, owner := range m.Status.Codeowners.Active {
159+
owners += " "
160+
owners += "@" + owner
161+
}
162+
codeowners += fmt.Sprintf("%s/%s @open-telemetry/collector-contrib-approvers%s\n", key, strings.Repeat(" ", data.maxLength-len(key)), owners)
163+
}
164+
}
165+
166+
codeowners += distributionCodeownersHeader
167+
longestName := 0
168+
for _, dist := range data.distributions {
169+
if longestName < len(dist.Name) {
170+
longestName = len(dist.Name)
171+
}
172+
}
173+
174+
for _, dist := range data.distributions {
175+
var maintainers []string
176+
for _, m := range dist.Maintainers {
177+
maintainers = append(maintainers, fmt.Sprintf("@%s", m))
178+
}
179+
180+
distribution := fmt.Sprintf("\nreports/distributions/%s.yaml%s @open-telemetry/collector-contrib-approvers", dist.Name, strings.Repeat(" ", longestName-len(dist.Name)))
181+
if len(maintainers) > 0 {
182+
distribution += fmt.Sprintf(" %s", strings.Join(maintainers, " "))
183+
}
184+
185+
codeowners += distribution
186+
}
187+
188+
err = os.WriteFile(filepath.Join(".github", "CODEOWNERS"), []byte(codeowners+unmaintainedCodeowners), 0o600)
189+
if err != nil {
190+
return err
191+
}
192+
err = os.WriteFile(filepath.Join(".github", "ALLOWLIST"), []byte(allowlistHeader+deprecatedList+unmaintainedList), 0o600)
193+
if err != nil {
194+
return err
195+
}
196+
return nil
197+
}
198+
199+
func (cg codeownersGenerator) getGithubMembers() (map[string]struct{}, error) {
200+
if cg.skipGithub {
201+
// don't try to get organization members if no token is expected
202+
return map[string]struct{}{}, nil
203+
}
204+
githubToken := os.Getenv("GITHUB_TOKEN")
205+
if githubToken == "" {
206+
return nil, fmt.Errorf("Set the environment variable `GITHUB_TOKEN` to a PAT token to authenticate")
207+
}
208+
client := github.NewClient(nil).WithAuthToken(githubToken)
209+
var allUsers []*github.User
210+
pageIndex := 0
211+
for {
212+
users, resp, err := client.Organizations.ListMembers(context.Background(), "open-telemetry",
213+
&github.ListMembersOptions{
214+
PublicOnly: false,
215+
ListOptions: github.ListOptions{
216+
PerPage: 50,
217+
Page: pageIndex,
218+
},
219+
},
220+
)
221+
if err != nil {
222+
return nil, err
223+
}
224+
defer resp.Body.Close()
225+
if len(users) == 0 {
226+
break
227+
}
228+
allUsers = append(allUsers, users...)
229+
pageIndex++
230+
}
231+
232+
usernames := make(map[string]struct{}, len(allUsers))
233+
for _, u := range allUsers {
234+
usernames[*u.Login] = struct{}{}
235+
}
236+
return usernames, nil
237+
}

cmd/githubgen/distributions.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package main
5+
6+
import (
7+
"fmt"
8+
"os"
9+
"path/filepath"
10+
"sort"
11+
12+
"gopkg.in/yaml.v3"
13+
)
14+
15+
type distributionsGenerator struct{}
16+
17+
type distOutput struct {
18+
Name string `yaml:"name"`
19+
URL string `yaml:"url"`
20+
Maintainers []string `yaml:"maintainers"`
21+
Components map[string][]string `yaml:"components"`
22+
}
23+
24+
func (cg distributionsGenerator) generate(data *githubData) error {
25+
for _, dist := range data.distributions {
26+
components := map[string][]string{}
27+
for _, c := range data.components {
28+
inDistro := false
29+
for _, componentDistro := range c.Status.Distributions {
30+
if dist.Name == componentDistro {
31+
inDistro = true
32+
break
33+
}
34+
}
35+
if inDistro {
36+
array, ok := components[c.Status.Class]
37+
if !ok {
38+
array = []string{}
39+
}
40+
components[c.Status.Class] = append(array, c.Type)
41+
}
42+
}
43+
for _, comps := range components {
44+
sort.Strings(comps)
45+
}
46+
output := distOutput{
47+
Name: dist.Name,
48+
URL: dist.URL,
49+
Maintainers: dist.Maintainers,
50+
Components: components,
51+
}
52+
b, err := yaml.Marshal(output)
53+
if err != nil {
54+
return nil
55+
}
56+
err = os.WriteFile(filepath.Join("reports", "distributions", fmt.Sprintf("%s.yaml", dist.Name)), b, 0o600)
57+
if err != nil {
58+
return nil
59+
}
60+
}
61+
return nil
62+
}

cmd/githubgen/go.mod

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Deprecated: use https://github.com/open-telemetry/opentelemetry-go-build-tools/tree/main/githubgen
2+
module github.com/open-telemetry/opentelemetry-collector-contrib/cmd/githubgen
3+
4+
go 1.22.0
5+
6+
require (
7+
github.com/google/go-github/v68 v68.0.0
8+
go.opentelemetry.io/collector/confmap v1.24.1-0.20250121185328-fbefb22cc2b3
9+
go.opentelemetry.io/collector/confmap/provider/fileprovider v1.24.1-0.20250121185328-fbefb22cc2b3
10+
gopkg.in/yaml.v3 v3.0.1
11+
)
12+
13+
require (
14+
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
15+
github.com/google/go-querystring v1.1.0 // indirect
16+
github.com/knadh/koanf/maps v0.1.1 // indirect
17+
github.com/knadh/koanf/providers/confmap v0.1.0 // indirect
18+
github.com/knadh/koanf/v2 v2.1.2 // indirect
19+
github.com/mitchellh/copystructure v1.2.0 // indirect
20+
github.com/mitchellh/reflectwalk v1.0.2 // indirect
21+
go.uber.org/multierr v1.11.0 // indirect
22+
go.uber.org/zap v1.27.0 // indirect
23+
)

0 commit comments

Comments
 (0)