Skip to content

Commit 47f6682

Browse files
authored
docs: Add README to each base example and add script to generate root README (#190)
* docs: Add README to each base example and add script to generate them * flip generation * add order support * Better error handling * Put everything into callout
1 parent 9256004 commit 47f6682

File tree

6 files changed

+236
-0
lines changed

6 files changed

+236
-0
lines changed

examples/base/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
<!-- THIS FILE IS AUTO-GENERATED, DO NOT EDIT MANUALLY! RUN "go run genreadme.go" TO RE-GENERATE -->
2+
13
# plugin-ci-workflows examples
24

35
> [!WARNING]
@@ -31,3 +33,4 @@ An example setup for a provisioned plugin. Use this workflow if you wish to have
3133

3234
- CI for each PR and push to main
3335
- Manual deployment to the catalog and Grafana Cloud via Argo workflow + deployment_tools
36+

examples/base/README.tmpl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!-- THIS FILE IS AUTO-GENERATED, DO NOT EDIT MANUALLY! RUN "go run genreadme.go" TO RE-GENERATE -->
2+
3+
# plugin-ci-workflows examples
4+
5+
> [!WARNING]
6+
>
7+
> Please [read the docs](https://enghub.grafana-ops.net/docs/default/component/grafana-plugins-platform/plugins-ci-github-actions/010-plugins-ci-github-actions) before using any of these workflows in your repository.
8+
9+
This folder contains some examples on how to use the shared workflows (CI and CD) in various scenarios.
10+
11+
The `yaml` files should be put in your repository's `.github/workflows` folder, and customized depending on your needs.
12+
13+
**Each workflow file is just a template/example. Remember to address all the TODOs before starting to use the workflows.**
14+
{{range .Subfolders}}
15+
## [`{{.FolderName}}`](./{{.FolderName}}/)
16+
17+
{{.Content}}
18+
{{end}}

examples/base/genreadme.go

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"log"
7+
"os"
8+
"path/filepath"
9+
"regexp"
10+
"sort"
11+
"strconv"
12+
"strings"
13+
"text/template"
14+
)
15+
16+
type SubfolderContent struct {
17+
FolderName string
18+
Content string
19+
Order int
20+
}
21+
22+
type ReadmeData struct {
23+
Subfolders []SubfolderContent
24+
}
25+
26+
const (
27+
tmplFileName = "README.tmpl"
28+
outputFileName = "README.md"
29+
readmeStartMarker = "<!-- README start -->"
30+
)
31+
32+
var orderRegex = regexp.MustCompile(`<!--\s*order:\s*(\d+)\s*-->`)
33+
34+
func _main() error {
35+
currentDir, err := os.Getwd()
36+
if err != nil {
37+
return fmt.Errorf("error getting current directory: %w", err)
38+
}
39+
40+
var subfolders []SubfolderContent
41+
42+
// Read all subdirectories
43+
entries, err := os.ReadDir(currentDir)
44+
if err != nil {
45+
return fmt.Errorf("error reading directory: %w", err)
46+
}
47+
48+
for _, entry := range entries {
49+
if !entry.IsDir() {
50+
continue
51+
}
52+
53+
folderName := entry.Name()
54+
readmePath := filepath.Join(currentDir, folderName, "README.md")
55+
56+
// Check if README.md exists in the subfolder
57+
if _, err := os.Stat(readmePath); os.IsNotExist(err) {
58+
continue
59+
}
60+
61+
// Extract content after "<!-- README start -->"
62+
content, order, err := extractContentAfterMarker(readmePath)
63+
if err != nil {
64+
log.Printf("Warning: Error processing %s: %v", readmePath, err)
65+
continue
66+
}
67+
68+
if content != "" {
69+
subfolders = append(subfolders, SubfolderContent{
70+
FolderName: folderName,
71+
Content: content,
72+
Order: order,
73+
})
74+
}
75+
}
76+
77+
// Sort subfolders by order
78+
sort.Slice(subfolders, func(i, j int) bool {
79+
return subfolders[i].Order < subfolders[j].Order
80+
})
81+
82+
// Load template from file
83+
tmpl, err := template.ParseFiles(tmplFileName)
84+
if err != nil {
85+
return fmt.Errorf("error parsing template file: %w", err)
86+
}
87+
88+
// Generate the root README.md
89+
data := ReadmeData{Subfolders: subfolders}
90+
91+
outputPath := filepath.Join(currentDir, outputFileName)
92+
file, err := os.Create(outputPath)
93+
if err != nil {
94+
return fmt.Errorf("error creating %s: %w", outputFileName, err)
95+
}
96+
defer func() {
97+
if cerr := file.Close(); cerr != nil {
98+
log.Printf("Warning: error closing file %s: %v", outputPath, cerr)
99+
}
100+
}()
101+
102+
err = tmpl.Execute(file, data)
103+
if err != nil {
104+
return fmt.Errorf("error executing template: %w", err)
105+
}
106+
107+
fmt.Printf("Generated %s with %d subfolders\n", outputFileName, len(subfolders))
108+
return nil
109+
}
110+
111+
func extractContentAfterMarker(filePath string) (string, int, error) {
112+
file, err := os.Open(filePath)
113+
if err != nil {
114+
return "", 0, err
115+
}
116+
defer file.Close()
117+
118+
scanner := bufio.NewScanner(file)
119+
var lines []string
120+
foundMarker := false
121+
order := 999 // Default order for files without order comment
122+
123+
for scanner.Scan() {
124+
line := scanner.Text()
125+
126+
// Check for order comment
127+
if matches := orderRegex.FindStringSubmatch(line); matches != nil {
128+
if orderNum, err := strconv.Atoi(matches[1]); err == nil {
129+
order = orderNum
130+
}
131+
continue // Don't include the order comment in the output
132+
}
133+
134+
if strings.Contains(line, readmeStartMarker) {
135+
foundMarker = true
136+
continue
137+
}
138+
139+
if foundMarker {
140+
lines = append(lines, line)
141+
}
142+
}
143+
144+
if err := scanner.Err(); err != nil {
145+
return "", 0, err
146+
}
147+
148+
if !foundMarker {
149+
return "", 0, fmt.Errorf("marker %q not found", readmeStartMarker)
150+
}
151+
152+
// Join lines and trim trailing whitespace
153+
content := strings.Join(lines, "\n")
154+
content = strings.TrimSpace(content)
155+
156+
return content, order, nil
157+
}
158+
159+
func main() {
160+
if err := _main(); err != nil {
161+
log.Fatalf("Error: %v", err)
162+
}
163+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# provisioned-plugin-auto-cd
2+
3+
> [!WARNING]
4+
>
5+
> Please [read the docs](https://enghub.grafana-ops.net/docs/default/component/grafana-plugins-platform/plugins-ci-github-actions/010-plugins-ci-github-actions) before using any of these workflows in your repository.
6+
>
7+
> The `yaml` files should be put in your repository's `.github/workflows` folder, and customized depending on your needs.
8+
>
9+
> **Each workflow file is just a template/example. Remember to address all the TODOs before starting to use the workflows.**
10+
11+
<!-- README start -->
12+
<!-- order: 10 -->
13+
14+
An example setup for a provisioned plugin with continuous delivery from the `main` branch. This is the **recommended** workflow to use for new plugins that want to be automatically installed on Grafana Cloud Instances.
15+
16+
- CI for each PR
17+
- CI + CD for each push to main: deployment to the catalog and Grafana Cloud ("dev", and optionally also "ops") via Argo workflow + deployment_tools
18+
- Manual deployment to the catalog and Grafana Cloud via Argo workflow + deployment_tools (for prod deployment)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# provisioned-plugin-manual-deployment
2+
3+
> [!WARNING]
4+
>
5+
> Please [read the docs](https://enghub.grafana-ops.net/docs/default/component/grafana-plugins-platform/plugins-ci-github-actions/010-plugins-ci-github-actions) before using any of these workflows in your repository.
6+
>
7+
> The `yaml` files should be put in your repository's `.github/workflows` folder, and customized depending on your needs.
8+
>
9+
> **Each workflow file is just a template/example. Remember to address all the TODOs before starting to use the workflows.**
10+
11+
<!-- README start -->
12+
<!-- order: 20 -->
13+
14+
An example setup for a provisioned plugin. Use this workflow if you wish to have manual control of version rollouts.
15+
16+
- CI for each PR and push to main
17+
- Manual deployment to the catalog and Grafana Cloud via Argo workflow + deployment_tools

examples/base/simple/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# simple
2+
3+
> [!WARNING]
4+
>
5+
> Please [read the docs](https://enghub.grafana-ops.net/docs/default/component/grafana-plugins-platform/plugins-ci-github-actions/010-plugins-ci-github-actions) before using any of these workflows in your repository.
6+
>
7+
> The `yaml` files should be put in your repository's `.github/workflows` folder, and customized depending on your needs.
8+
>
9+
> **Each workflow file is just a template/example. Remember to address all the TODOs before starting to use the workflows.**
10+
11+
<!-- README start -->
12+
<!-- order: 0 -->
13+
14+
A simple setup for a non-provisioned plugin, gets you started quickly and you can test your plugin on a grafana cloud instance.
15+
16+
- CI for each PR and push to main
17+
- Manual deployment to the catalog

0 commit comments

Comments
 (0)