Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validation Script for OC Path and RPC Coverage in READMEs #2865

Merged
merged 19 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/readme_oc_path_and_rpc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: README OpenConfig Path and RPC Coverage

on:
push:
branches: [ main ]
pull_request:
schedule:
- cron: "49 0 * * *"

jobs:
integration-test:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: stable
cache: false

- name: Validate Validation Script
run: |
cd tools/validate_readme_spec
./validate_readme_spec_test.sh

- name: Validate Template README
run: |
go run tools/validate_readme_spec/validate_readme_spec.go -alsologtostderr doc/test-requirements-template.md; rm -rf tmp

- name: Validate Test READMEs
run: |
# TODO: Add READMEs here that have converted to the new format.
dplore marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ require (
github.com/pborman/uuid v1.2.1
github.com/protocolbuffers/txtpbfmt v0.0.0-20220608084003-fc78c767cd6a
github.com/yoheimuta/go-protoparser/v4 v4.9.0
github.com/yuin/goldmark v1.4.13
golang.org/x/crypto v0.21.0
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8
golang.org/x/text v0.14.0
google.golang.org/api v0.162.0
google.golang.org/grpc v1.63.0
google.golang.org/protobuf v1.33.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/klog/v2 v2.100.1
)

Expand Down Expand Up @@ -159,7 +161,6 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.26.3 // indirect
k8s.io/apimachinery v0.26.3 // indirect
k8s.io/client-go v0.26.3 // indirect
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1812,6 +1812,7 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
Expand Down
87 changes: 87 additions & 0 deletions tools/internal/mdocspec/md.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package mdocspec

import (
"io"

"github.com/yuin/goldmark"
"github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/extension"
"github.com/yuin/goldmark/renderer"
)

const (
// OCSpecHeading is the MarkDown heading that MUST precede the yaml
// section containing the OC path and RPC listing.
OCSpecHeading = "OpenConfig Path and RPC Coverage"
)

type mdOCSpecs struct{}

// MDOCSpecs is an extension that only renders the first yaml block from a
// functional test README that comes after the pre-established OC Spec heading
// `OCSpecHeading`.
var MDOCSpecs = &mdOCSpecs{}

func (e *mdOCSpecs) Extend(m goldmark.Markdown) {
extension.GFM.Extend(m)
m.SetRenderer(&yamlRenderer{})
}

type yamlRenderer struct{}

func (r *yamlRenderer) Render(w io.Writer, source []byte, n ast.Node) error {
return ast.Walk(n, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
return renderYAML(w, source, n, entering)
})
}

func (r *yamlRenderer) AddOptions(...renderer.Option) {}

func ocSpecHeading(source []byte, n ast.Node) (heading *ast.Heading, ok bool) {
if h, ok := n.(*ast.Heading); ok {
headingSegment := h.Lines().At(0)
if string(headingSegment.Value(source)) == OCSpecHeading {
return h, true
}
}
return nil, false
}

func yamlCodeBlock(source []byte, n ast.Node) (block *ast.FencedCodeBlock, ok bool) {
if c, ok := n.(*ast.FencedCodeBlock); ok && c.Info != nil {
if lang := c.Info.Text(source); len(lang) > 0 && string(lang) == "yaml" {
return c, true
}
}
return nil, false
}

func renderYAML(w io.Writer, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
if !entering {
return ast.WalkContinue, nil
}
heading, ok := ocSpecHeading(source, n)
if !ok {
return ast.WalkContinue, nil
}
// Check if prior to the next heading of the same level,
// a yaml code block can be found.
for next := heading.NextSibling(); next != nil; next = next.NextSibling() {
if h, ok := next.(*ast.Heading); ok && h.Level <= heading.Level {
// End of heading reached.
return ast.WalkContinue, nil
}
if c, ok := yamlCodeBlock(source, next); ok {
l := c.Lines().Len()
for i := 0; i != l; i++ {
line := c.Lines().At(i)
if _, err := w.Write(line.Value(source)); err != nil {
return ast.WalkStop, err
}
}
// Stop after finding the first such YAML block.
return ast.WalkStop, nil
dplore marked this conversation as resolved.
Show resolved Hide resolved
}
}
return ast.WalkContinue, nil
}
Loading
Loading