summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--Makefile14
-rw-r--r--generator/.gitignore1
-rw-r--r--generator/Dockerfile8
-rw-r--r--generator/Dockerfile.test8
-rw-r--r--generator/README.md6
-rw-r--r--generator/app.go163
-rw-r--r--generator/app_test.go127
-rw-r--r--generator/list.tmpl (renamed from generator/sig_list.tmpl)2
-rw-r--r--generator/sig_readme.tmpl (renamed from generator/sig_index.tmpl)0
-rw-r--r--generator/testdata/custom_content.md2
-rw-r--r--generator/testdata/example.md2
-rw-r--r--generator/testdata/no_custom_content.md2
-rw-r--r--generator/testdata/sigs.yaml5
-rw-r--r--generator/wg_readme.tmpl (renamed from generator/wg_index.tmpl)2
-rw-r--r--sigs.yaml4
16 files changed, 217 insertions, 130 deletions
diff --git a/.travis.yml b/.travis.yml
index 1b870ea5..e6db9e8a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,4 +6,5 @@ services:
- docker
script:
+ - make test-unit
- bash ./scripts/verify.sh
diff --git a/Makefile b/Makefile
index 7406d281..1061bd63 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,5 @@
+IMAGE_NAME=kube-communitydocs
+
all: \
build-image \
gen-docs \
@@ -6,14 +8,10 @@ reset-docs:
git checkout HEAD -- sig-list.md sig-*
build-image:
- docker build -t sigdocs -f generator/Dockerfile generator
-
-gen-doc:
- docker run -e WG=${WG} -e SIG=${SIG} -v $(shell pwd):/go/src/app sigdocs
+ docker build -t $(IMAGE_NAME) -f generator/Dockerfile generator
gen-docs:
- docker run -v $(shell pwd):/go/src/app sigdocs
+ docker run --rm -e WG -e SIG -v $(shell pwd):/go/src/app/generated $(IMAGE_NAME) app
-test:
- docker build -t sigdocs-test -f generator/Dockerfile.test generator
- docker run sigdocs-test
+test: build-image
+ docker run --rm $(IMAGE_NAME) go test -v ./...
diff --git a/generator/.gitignore b/generator/.gitignore
new file mode 100644
index 00000000..9ab870da
--- /dev/null
+++ b/generator/.gitignore
@@ -0,0 +1 @@
+generated/
diff --git a/generator/Dockerfile b/generator/Dockerfile
index f1b21921..deffa8a9 100644
--- a/generator/Dockerfile
+++ b/generator/Dockerfile
@@ -1 +1,7 @@
-FROM golang:1.8-onbuild
+FROM golang:1.8
+
+WORKDIR /go/src/app
+COPY . .
+
+RUN go-wrapper download
+RUN go-wrapper install
diff --git a/generator/Dockerfile.test b/generator/Dockerfile.test
deleted file mode 100644
index f8807831..00000000
--- a/generator/Dockerfile.test
+++ /dev/null
@@ -1,8 +0,0 @@
-FROM golang:1.8
-
-WORKDIR /go/src/app
-COPY . .
-
-RUN go-wrapper download
-
-CMD ["go", "test", "./..."]
diff --git a/generator/README.md b/generator/README.md
index 3fd2230e..d2382aa5 100644
--- a/generator/README.md
+++ b/generator/README.md
@@ -33,9 +33,9 @@ make all
To build docs for one SIG, run these commands:
```bash
-make SIG=sig-apps gen-doc
-make SIG=sig-testing gen-doc
-make WG=resource-management gen-doc
+make SIG=sig-apps gen-docs
+make SIG=sig-testing gen-docs
+make WG=resource-management gen-docs
```
where the `SIG` or `WG` var refers to the directory being built.
diff --git a/generator/app.go b/generator/app.go
index 9cfb45b8..63344131 100644
--- a/generator/app.go
+++ b/generator/app.go
@@ -30,24 +30,29 @@ import (
)
var (
- sigsYamlFile = "sigs.yaml"
- sigIndexTemplate = "sig_index.tmpl"
- wgIndexTemplate = "wg_index.tmpl"
- listTemplate = "sig_list.tmpl"
- headerTemplate = "header.tmpl"
- sigListOutput = "sig-list.md"
- sigIndexOutput = "README.md"
- githubTeamNames = []string{"misc", "test-failures", "bugs", "feature-requests", "proposals", "pr-reviews", "api-reviews"}
- beginMarker = "<!-- BEGIN CUSTOM CONTENT -->"
- endMarker = "<!-- END CUSTOM CONTENT -->"
+ readmeTemplate = "readme.tmpl"
+ listTemplate = "list.tmpl"
+ headerTemplate = "header.tmpl"
+
+ sigsYamlFile = "sigs.yaml"
+ sigListOutput = "sig-list.md"
+ indexFilename = "README.md"
+ baseOutputDir = "generated"
+
+ githubTeamNames = []string{"misc", "test-failures", "bugs", "feature-requests", "proposals", "pr-reviews", "api-reviews"}
+ beginMarker = "<!-- BEGIN CUSTOM CONTENT -->"
+ endMarker = "<!-- END CUSTOM CONTENT -->"
)
+// Lead represents a lead engineer for a particular group. There are usually
+// 2 per group.
type Lead struct {
Name string
Company string
GitHub string
}
+// Meeting represents a regular meeting for a group.
type Meeting struct {
Day string
UTC string
@@ -55,6 +60,7 @@ type Meeting struct {
Frequency string
}
+// Contact represents the various contact points for a group.
type Contact struct {
Slack string
MailingList string `yaml:"mailing_list"`
@@ -63,7 +69,8 @@ type Contact struct {
GithubTeamNames []string
}
-type Sig struct {
+// Group represents either a Special Interest Group (SIG) or a Working Group (WG)
+type Group struct {
Name string
Dir string
MissionStatement string `yaml:"mission_statement"`
@@ -74,28 +81,31 @@ type Sig struct {
Contact Contact
}
-type Wg struct {
- Name string
- Dir string
- MissionStatement string `yaml:"mission_statement"`
- Organizers []Lead
- Meetings []Meeting
- MeetingURL string `yaml:"meeting_url"`
- MeetingArchiveURL string `yaml:"meeting_archive_url"`
- Contact Contact
+// DirName returns the directory that a group's documentation will be
+// generated into. It is composed of a prefix (sig for SIGs and wg for WGs),
+// and a formatted version of the group's name (in kebab case).
+func (e *Group) DirName(prefix string) string {
+ return fmt.Sprintf("%s-%s", prefix, strings.ToLower(strings.Replace(e.Name, " ", "-", -1)))
}
-type Context struct {
- Sigs []Sig
- WorkingGroups []Wg
-}
+// SetupGitHubTeams will iterate over all the possible teams available to a
+// group (these are defined by the Kubernetes organisation) and populate a
+// list using the group's prefix.
+func (e *Group) SetupGitHubTeams(prefix string) {
+ ghPrefix := e.Contact.GithubTeamPrefix
+ if ghPrefix == "" {
+ ghPrefix = e.DirName(prefix)
+ }
-type SigEntries struct {
- Sigs []Sig
+ for _, gtn := range githubTeamNames {
+ e.Contact.GithubTeamNames = append(e.Contact.GithubTeamNames, fmt.Sprintf("%s-%s", ghPrefix, gtn))
+ }
}
-type WgEntries struct {
- WorkingGroups []Wg
+// Context is the context for the sigs.yaml file.
+type Context struct {
+ Sigs []Group
+ WorkingGroups []Group
}
func pathExists(path string) bool {
@@ -105,8 +115,7 @@ func pathExists(path string) bool {
func createDirIfNotExists(path string) error {
if !pathExists(path) {
- fmt.Printf("%s directory does not exist, creating\n", path)
- return os.Mkdir(path, 0755)
+ return os.MkdirAll(path, 0755)
}
return nil
}
@@ -137,13 +146,7 @@ func getExistingContent(path string) (string, error) {
return strings.Join(captured, "\n"), nil
}
-func writeTemplate(templateFilePath, outputPath string, data interface{}) error {
- wd, err := os.Getwd()
- if err != nil {
- return err
- }
- templatePath := filepath.Join(wd, templateFilePath)
-
+func writeTemplate(templatePath, outputPath string, data interface{}) error {
// set up template
t, err := template.ParseFiles(templatePath, headerTemplate)
if err != nil {
@@ -152,7 +155,7 @@ func writeTemplate(templateFilePath, outputPath string, data interface{}) error
// create if not exists
if !pathExists(outputPath) {
- _, err := os.Create(outputPath)
+ _, err = os.Create(outputPath)
if err != nil {
return err
}
@@ -183,7 +186,6 @@ func writeTemplate(templateFilePath, outputPath string, data interface{}) error
// custom content block
writeCustomContentBlock(f, content)
- fmt.Printf("Generated %s\n", outputPath)
return nil
}
@@ -194,61 +196,33 @@ func writeCustomContentBlock(f *os.File, content string) {
}
}
-func createReadmeFiles(ctx Context) error {
- var selectedSig *string
- if sig, ok := os.LookupEnv("SIG"); ok {
- selectedSig = &sig
+func createGroupReadme(groups []Group, prefix string) error {
+ // figure out if the user wants to generate one group
+ var selectedGroupName *string
+ if envVal, ok := os.LookupEnv(strings.ToUpper(prefix)); ok {
+ selectedGroupName = &envVal
}
- for _, sig := range ctx.Sigs {
- dirName := fmt.Sprintf("sig-%s", strings.ToLower(strings.Replace(sig.Name, " ", "-", -1)))
- if selectedSig != nil && *selectedSig != dirName {
- fmt.Printf("Skipping %s\n", dirName)
+ for _, group := range groups {
+ group.Dir = group.DirName(prefix)
+ // skip generation if the user specified only one group
+ if selectedGroupName != nil && *selectedGroupName != group.Dir {
+ fmt.Printf("Skipping %s/README.md\n", group.Dir)
continue
}
- createDirIfNotExists(dirName)
-
- prefix := sig.Contact.GithubTeamPrefix
- if prefix == "" {
- prefix = dirName
- }
-
- for _, gtn := range githubTeamNames {
- sig.Contact.GithubTeamNames = append(sig.Contact.GithubTeamNames, fmt.Sprintf("%s-%s", prefix, gtn))
- }
+ fmt.Printf("Generating %s/README.md\n", group.Dir)
- outputPath := fmt.Sprintf("%s/%s", dirName, sigIndexOutput)
- if err := writeTemplate(sigIndexTemplate, outputPath, sig); err != nil {
+ outputDir := filepath.Join(baseOutputDir, group.Dir)
+ if err := createDirIfNotExists(outputDir); err != nil {
return err
}
- }
-
- var selectedWg *string
- if wg, ok := os.LookupEnv("WG"); ok {
- selectedWg = &wg
- }
- for _, wg := range ctx.WorkingGroups {
- dirName := fmt.Sprintf("wg-%s", strings.ToLower(strings.Replace(wg.Name, " ", "-", -1)))
-
- if selectedWg != nil && *selectedWg != dirName {
- fmt.Printf("Skipping %s\n", dirName)
- continue
- }
-
- createDirIfNotExists(dirName)
-
- prefix := wg.Contact.GithubTeamPrefix
- if prefix == "" {
- prefix = dirName
- }
- for _, gtn := range githubTeamNames {
- wg.Contact.GithubTeamNames = append(wg.Contact.GithubTeamNames, fmt.Sprintf("%s-%s", prefix, gtn))
- }
+ group.SetupGitHubTeams(prefix)
- outputPath := fmt.Sprintf("%s/%s", dirName, sigIndexOutput)
- if err := writeTemplate(wgIndexTemplate, outputPath, wg); err != nil {
+ outputPath := filepath.Join(outputDir, indexFilename)
+ readmePath := fmt.Sprintf("%s_%s", prefix, readmeTemplate)
+ if err := writeTemplate(readmePath, outputPath, group); err != nil {
return err
}
}
@@ -256,12 +230,8 @@ func createReadmeFiles(ctx Context) error {
return nil
}
-func createListFile(ctx Context) error {
- return writeTemplate(listTemplate, sigListOutput, ctx)
-}
-
func main() {
- yamlData, err := ioutil.ReadFile(sigsYamlFile)
+ yamlData, err := ioutil.ReadFile(filepath.Join(baseOutputDir, sigsYamlFile))
if err != nil {
log.Fatal(err)
}
@@ -273,19 +243,26 @@ func main() {
}
sort.Slice(ctx.Sigs, func(i, j int) bool {
- return ctx.Sigs[i].Name >= ctx.Sigs[j].Name
+ return ctx.Sigs[i].Name <= ctx.Sigs[j].Name
})
sort.Slice(ctx.WorkingGroups, func(i, j int) bool {
- return ctx.WorkingGroups[i].Name >= ctx.WorkingGroups[j].Name
+ return ctx.WorkingGroups[i].Name <= ctx.WorkingGroups[j].Name
})
- err = createReadmeFiles(ctx)
+ err = createGroupReadme(ctx.Sigs, "sig")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ err = createGroupReadme(ctx.WorkingGroups, "wg")
if err != nil {
log.Fatal(err)
}
- err = createListFile(ctx)
+ fmt.Println("Generating sig-list.md")
+ outputPath := filepath.Join(baseOutputDir, sigListOutput)
+ err = writeTemplate(listTemplate, outputPath, ctx)
if err != nil {
log.Fatal(err)
}
diff --git a/generator/app_test.go b/generator/app_test.go
index 1ef3a574..c71471c7 100644
--- a/generator/app_test.go
+++ b/generator/app_test.go
@@ -17,7 +17,11 @@ limitations under the License.
package main
import (
+ "fmt"
"io/ioutil"
+ "os"
+ "path/filepath"
+ "reflect"
"strings"
"testing"
)
@@ -33,6 +37,14 @@ func TestNonExistantDirIsCreated(t *testing.T) {
}
}
+func TestExistantDirNotCreated(t *testing.T) {
+ dir := "./testdata"
+ err := createDirIfNotExists(dir)
+ if err != nil {
+ t.Fatalf("Received error creating dir: %v", err)
+ }
+}
+
func TestGetExistingData(t *testing.T) {
cases := []struct {
path string
@@ -105,13 +117,6 @@ content!
data: map[string]string{"Message": "Hello!"},
expected: customContent,
},
- {
- templatePath: "./testdata/example.tmpl",
- outputPath: "/tmp/non_existing_path.md",
- expectErr: false,
- data: map[string]string{"Message": "Hello!"},
- expected: "Last generated: ",
- },
}
for _, c := range cases {
@@ -134,3 +139,111 @@ content!
}
}
}
+
+func TestGroupDirName(t *testing.T) {
+ group := Group{Name: "Foo Bar"}
+ if group.DirName("sig") != "sig-foo-bar" {
+ t.Fatal("DirName incorrect")
+ }
+}
+
+func TestSetupGithubTeams(t *testing.T) {
+ group := Group{Name: "Foo Bar"}
+ group.SetupGitHubTeams("sig")
+
+ var expected []string
+ for _, ght := range githubTeamNames {
+ expected = append(expected, fmt.Sprintf("sig-foo-bar-%s", ght))
+ }
+
+ if !reflect.DeepEqual(group.Contact.GithubTeamNames, expected) {
+ t.Fatalf("%v does not match %v", group.Contact.GithubTeamNames, expected)
+ }
+}
+
+func TestCustomPrefixSetupGithubTeams(t *testing.T) {
+ group := Group{Contact: Contact{GithubTeamPrefix: "foo"}}
+ group.SetupGitHubTeams("")
+
+ var expected []string
+ for _, ght := range githubTeamNames {
+ expected = append(expected, fmt.Sprintf("foo-%s", ght))
+ }
+
+ if !reflect.DeepEqual(group.Contact.GithubTeamNames, expected) {
+ t.Fatalf("%v does not match %v", group.Contact.GithubTeamNames, expected)
+ }
+}
+
+func TestCreateGroupReadmes(t *testing.T) {
+ groups := []Group{
+ Group{Name: "Foo"},
+ Group{Name: "Bar"},
+ }
+
+ err := createGroupReadme(groups, "sig")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for _, group := range groups {
+ path := filepath.Join(baseOutputDir, group.DirName("sig"), "README.md")
+ if !pathExists(path) {
+ t.Fatalf("%s should exist", path)
+ }
+ }
+}
+
+func TestReadmesAreSkipped(t *testing.T) {
+ os.Setenv("SIG", "sig-foo")
+
+ groups := []Group{
+ Group{Name: "Foo"},
+ Group{Name: "Bar"},
+ }
+
+ err := createGroupReadme(groups, "sig")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for _, group := range groups[1:] {
+ path := filepath.Join(baseOutputDir, group.DirName("sig"), "README.md")
+ if !pathExists(path) {
+ t.Fatalf("%s should exist", path)
+ }
+ }
+
+ os.Setenv("SIG", "")
+}
+
+func copyFile(src, dst string) error {
+ // Read all content of src to data
+ data, err := ioutil.ReadFile(src)
+ if err != nil {
+ return err
+ }
+ // Write data to dst
+ err = ioutil.WriteFile(dst, data, 0644)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func TestFullGeneration(t *testing.T) {
+ err := copyFile("testdata/sigs.yaml", "generated/sigs.yaml")
+ if err != nil {
+ t.Fatalf("Error received: %v", err)
+ }
+
+ main()
+
+ expectedDirs := []string{"sig-foo", "sig-bar", "wg-baz"}
+ for _, ed := range expectedDirs {
+ path := filepath.Join(baseOutputDir, ed, "README.md")
+ if !pathExists(path) {
+ t.Fatalf("%s should exist", path)
+ }
+ }
+}
diff --git a/generator/sig_list.tmpl b/generator/list.tmpl
index 01c5782c..f911529e 100644
--- a/generator/sig_list.tmpl
+++ b/generator/list.tmpl
@@ -24,5 +24,5 @@ When the need arises, a [new SIG can be created](sig-creation-procedure.md)
| Name | Organizers | Contact | Meetings |
|------|------------|---------|----------|
{{- range .WorkingGroups}}
-|[{{.Name}}]({{.Dir}}/README.md)|{{range .Organizers}}* [{{.Name}}](https://github.com/{{.GitHub}}){{if .Company}}, {{.Company}}{{end}}<br>{{end}}|* [Slack](https://kubernetes.slack.com/messages/{{.Contact.Slack}})<br>* [Mailing List]({{.Contact.MailingList}})|{{ $save := . }}{{range .Meetings}}* [{{.Day}}s at {{.UTC}} UTC ({{.Frequency}})]({{$save.MeetingURL}})<br>{{end}}
+|[{{.Name}}]({{.Dir}}/README.md)|{{range .Leads}}* [{{.Name}}](https://github.com/{{.GitHub}}){{if .Company}}, {{.Company}}{{end}}<br>{{end}}|* [Slack](https://kubernetes.slack.com/messages/{{.Contact.Slack}})<br>* [Mailing List]({{.Contact.MailingList}})|{{ $save := . }}{{range .Meetings}}* [{{.Day}}s at {{.UTC}} UTC ({{.Frequency}})]({{$save.MeetingURL}})<br>{{end}}
{{- end }}
diff --git a/generator/sig_index.tmpl b/generator/sig_readme.tmpl
index 54ee8d57..54ee8d57 100644
--- a/generator/sig_index.tmpl
+++ b/generator/sig_readme.tmpl
diff --git a/generator/testdata/custom_content.md b/generator/testdata/custom_content.md
index 501f56b4..592088e3 100644
--- a/generator/testdata/custom_content.md
+++ b/generator/testdata/custom_content.md
@@ -27,5 +27,3 @@ Meeting notes and Agenda can be found [here](https://docs.google.com/document/d/
<!-- BEGIN CUSTOM CONTENT -->
FOO BAR BAZ
<!-- END CUSTOM CONTENT -->
-
-Last generated: Wed Jun 7 2017 14:27:56
diff --git a/generator/testdata/example.md b/generator/testdata/example.md
index 63ddbe7b..9016ae83 100644
--- a/generator/testdata/example.md
+++ b/generator/testdata/example.md
@@ -5,5 +5,3 @@ custom
content!
<!-- END CUSTOM CONTENT -->
-
-Last generated: Thu Jun 15 2017 15:20:28 \ No newline at end of file
diff --git a/generator/testdata/no_custom_content.md b/generator/testdata/no_custom_content.md
index 737509fd..34299789 100644
--- a/generator/testdata/no_custom_content.md
+++ b/generator/testdata/no_custom_content.md
@@ -27,5 +27,3 @@ Meeting notes and Agenda can be found [here](https://docs.google.com/document/d/
<!-- BEGIN CUSTOM CONTENT -->
<!-- END CUSTOM CONTENT -->
-
-Last generated: Wed Jun 7 2017 14:27:56
diff --git a/generator/testdata/sigs.yaml b/generator/testdata/sigs.yaml
new file mode 100644
index 00000000..a4fe858c
--- /dev/null
+++ b/generator/testdata/sigs.yaml
@@ -0,0 +1,5 @@
+sigs:
+ - name: Foo
+ - name: Bar
+workinggroups:
+ - name: Baz
diff --git a/generator/wg_index.tmpl b/generator/wg_readme.tmpl
index ed8fc9c0..9a0144a6 100644
--- a/generator/wg_index.tmpl
+++ b/generator/wg_readme.tmpl
@@ -10,7 +10,7 @@
Meeting notes and Agenda can be found [here]({{.MeetingArchiveURL}}).
## Organizers
-{{- range .Organizers }}
+{{- range .Leads }}
* [{{.Name}}](https://github.com/{{.GitHub}}){{if .Company}}, {{.Company}}{{end}}
{{- end }}
diff --git a/sigs.yaml b/sigs.yaml
index af3b0185..f3ab0518 100644
--- a/sigs.yaml
+++ b/sigs.yaml
@@ -627,7 +627,7 @@ workinggroups:
dir: wg-resource-management
mission_statement: >
Designing and shepherding cross-cutting features around compute resource isolation and utilization.
- organizers:
+ leads:
- name: Vishnu Kannan
github: vishh
company: Google
@@ -642,4 +642,4 @@ workinggroups:
meeting_archive_url: https://www.youtube.com/playlist?list=PL69nYSiGNLP1wJPj5DYWXjiArF-MJ5fNG
contact:
slack: wg-resource-mgmt
- mailing_list: https://groups.google.com/forum/#!forum/kubernetes-wg-resource-management \ No newline at end of file
+ mailing_list: https://groups.google.com/forum/#!forum/kubernetes-wg-resource-management