Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
17 changes: 9 additions & 8 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,32 @@ on:
push:
branches:
- '**'
# - $default-branch
pull_request:
branches:
- '**'
# - $default-branch

jobs:
build:
runs-on: ubuntu-latest
env:
COVER: true
runs-on: ubuntu-20.04

steps:

- name: Check out code
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Set up Go 1.17
uses: actions/setup-go@v2
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.17.x
go-version-file: reference-gen/go.mod
id: go

- name: Get dependencies
env:
GOLANGCI_LINT_VERSION: v1.63.4
run: |
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.36.0
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin ${GOLANGCI_LINT_VERSION}
curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
chmod +x ./cc-test-reporter

Expand Down
18 changes: 4 additions & 14 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,22 @@ jobs:
strategy:
fail-fast: false

# CodeQL runs on ubuntu-latest and windows-latest
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2

# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
uses: actions/checkout@v4

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v3
with:
languages: go

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v3

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
Expand All @@ -54,4 +44,4 @@ jobs:
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v3
2 changes: 1 addition & 1 deletion .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/stale@v1
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue has been inactive for 60 days. If the issue is still relevant please comment to re-activate the issue. If no action is taken within 7 days, the issue will be marked closed.'
Expand Down
4 changes: 2 additions & 2 deletions reference-gen/go.mod
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
module github.com/oauth2-proxy/tools/reference-gen

go 1.17
go 1.22

require (
github.com/go-git/go-git/v5 v5.4.2
github.com/onsi/ginkgo v1.14.1
github.com/onsi/gomega v1.10.2
github.com/sergi/go-diff v1.1.0
github.com/spf13/pflag v1.0.5
k8s.io/gengo v0.0.0-20201113003025-83324d819ded
k8s.io/klog/v2 v2.4.0
Expand All @@ -15,7 +16,6 @@ require (
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/go-logr/logr v0.2.0 // indirect
github.com/nxadm/tail v1.4.4 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
golang.org/x/net v0.0.0-20210326060303-6b1517762897 // indirect
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79 // indirect
golang.org/x/text v0.3.3 // indirect
Expand Down
5 changes: 2 additions & 3 deletions reference-gen/pkg/generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"text/template"
Expand Down Expand Up @@ -68,7 +67,7 @@ func loadHeaderText(fileName string) ([]byte, error) {
return []byte{}, nil
}

headerText, err := ioutil.ReadFile(fileName)
headerText, err := os.ReadFile(fileName)
if err != nil {
return nil, fmt.Errorf("error reading file: %v", err)
}
Expand Down Expand Up @@ -184,7 +183,7 @@ func (g *generator) writeOutput(content []byte) error {
return nil
}

if err := ioutil.WriteFile(g.outputFileName, content, 0600); err != nil {
if err := os.WriteFile(g.outputFileName, content, 0600); err != nil {
return fmt.Errorf("could not write file %q: %v", g.outputFileName, err)
}
klog.Infof("Rendered output written to %q", g.outputFileName)
Expand Down
63 changes: 32 additions & 31 deletions reference-gen/pkg/generator/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"embed"
"fmt"
"io/ioutil"
"os"
"strings"

Expand All @@ -16,7 +15,7 @@ import (
)

const (
testDataPackage = "github.com/oauth2-proxy/tools/reference-gen/pkg/generator/testdata"
testDataPackage = "github.com/oauth2-proxy/tools/reference-gen/pkg/generator/testdata/"
)

//go:embed testdata/*.md
Expand All @@ -29,35 +28,37 @@ var _ = Describe("Generator", func() {
expectedOutputFileName string
}

DescribeTable("should generate the expected output", func(in generatorTableInput) {
By("Creating an output file")
outputFile, err := ioutil.TempFile("", "oauth2-proxy-reference-generator-suite-")
Expect(err).ToNot(HaveOccurred())

outputFileName := outputFile.Name()
Expect(outputFile.Close()).To(Succeed())

By("Constructing the generator")
gen, err := NewGenerator(testDataPackage, in.requestedTypes, in.headerFileName, outputFileName, "")
Expect(err).ToNot(HaveOccurred())

By("Running the generator")
Expect(gen.Run()).To(Succeed())

By("Loading the output")
output, err := os.ReadFile(outputFileName)
Expect(err).ToNot(HaveOccurred())

By("Loading the expected output")
expectedOutput, err := testOutputs.ReadFile(in.expectedOutputFileName)
Expect(err).ToNot(HaveOccurred())

By("Comparing the outputs")
diffs := diff.Do(string(expectedOutput), string(output))
if len(diffs) > 1 {
// A single diff means the two files are equal, only fail if there is more than one diff.
fmt.Printf("\nUnexpected diff:\n\n%s\n", prettyPrintDiff(diffs))
Fail("Unexpected diff in generated output")
DescribeTable("should generate the expected output for json & yaml tags", func(in generatorTableInput) {
for _, pkg := range []string{"json", "yaml"} {
By(pkg + ": Creating an output file")
outputFile, err := os.CreateTemp("", pkg+"-oauth2-proxy-reference-generator-suite-")
Expect(err).ToNot(HaveOccurred())

outputFileName := outputFile.Name()
Expect(outputFile.Close()).To(Succeed())

By(pkg + ": Constructing the generator")
gen, err := NewGenerator(testDataPackage+pkg, in.requestedTypes, in.headerFileName, outputFileName, "")
Expect(err).ToNot(HaveOccurred())

By(pkg + ": Running the generator")
Expect(gen.Run()).To(Succeed())

By(pkg + ": Loading the output")
output, err := os.ReadFile(outputFileName)
Expect(err).ToNot(HaveOccurred())

By(pkg + ": Loading the expected output")
expectedOutput, err := testOutputs.ReadFile(in.expectedOutputFileName)
Expect(err).ToNot(HaveOccurred())

By(pkg + ": Comparing the outputs")
diffs := diff.Do(string(expectedOutput), string(output))
if len(diffs) > 1 {
// A single diff means the two files are equal, only fail if there is more than one diff.
fmt.Printf("\n%s: Unexpected diff:\n\n%s\n", pkg, prettyPrintDiff(diffs))
Fail(pkg + ": Unexpected diff in generated output")
}
}
},
Entry("With the full test structure, pulls in references for all substructs", generatorTableInput{
Expand Down
6 changes: 3 additions & 3 deletions reference-gen/pkg/generator/testdata/fullMyTestStruct.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ members table as the origin struct.

| Field | Type | Description |
| ----- | ---- | ----------- |
| `NonTaggedField` | _bool_ | NonTaggedField doesn't have a json tag, so the name will be capitalised. |
| `NonTaggedField` | _bool_ | NonTaggedField doesn't have a tag, so the name will be capitalised. |

### AliasedExternalMap
#### (`map[string]interface{}` alias)
#### (`map[string]any` alias)

(**Appears on:** [MyTestStruct](#myteststruct))

Expand Down Expand Up @@ -77,4 +77,4 @@ SomeSubStruct is a struct to go within another struct.

| Field | Type | Description |
| ----- | ---- | ----------- |
| `NonTaggedField` | _bool_ | NonTaggedField doesn't have a json tag, so the name will be capitalised. |
| `NonTaggedField` | _bool_ | NonTaggedField doesn't have a tag, so the name will be capitalised. |
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package testdata
package json

import (
"text/template"
Expand Down Expand Up @@ -63,7 +63,7 @@ type MyTestStruct struct {

// SomeSubStruct is a struct to go within another struct.
type SomeSubStruct struct {
// NonTaggedField doesn't have a json tag, so the name will be capitalised.
// NonTaggedField doesn't have a tag, so the name will be capitalised.
NonTaggedField bool

// privateStruct should not be included in the docs.
Expand Down
2 changes: 1 addition & 1 deletion reference-gen/pkg/generator/testdata/someSubStructOnly.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ SomeSubStruct is a struct to go within another struct.

| Field | Type | Description |
| ----- | ---- | ----------- |
| `NonTaggedField` | _bool_ | NonTaggedField doesn't have a json tag, so the name will be capitalised. |
| `NonTaggedField` | _bool_ | NonTaggedField doesn't have a tag, so the name will be capitalised. |
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ SomeSubStruct is a struct to go within another struct.

| Field | Type | Description |
| ----- | ---- | ----------- |
| `NonTaggedField` | _bool_ | NonTaggedField doesn't have a json tag, so the name will be capitalised. |
| `NonTaggedField` | _bool_ | NonTaggedField doesn't have a tag, so the name will be capitalised. |
2 changes: 1 addition & 1 deletion reference-gen/pkg/generator/testdata/unrelatedStructs.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ SomeSubStruct is a struct to go within another struct.

| Field | Type | Description |
| ----- | ---- | ----------- |
| `NonTaggedField` | _bool_ | NonTaggedField doesn't have a json tag, so the name will be capitalised. |
| `NonTaggedField` | _bool_ | NonTaggedField doesn't have a tag, so the name will be capitalised. |
98 changes: 98 additions & 0 deletions reference-gen/pkg/generator/testdata/yaml/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package types

import (
"text/template"
"time"
)

// MyTestStruct contains a collection of fields all attempting to test various
// aspects of the code generation.
type MyTestStruct struct {
// Name is the name of the MyTestStruct.
Name string `yaml:"name"`

// privateField is a private field and so should not be documented
// in the generated docs.
privateField string

// LongMessageInt has a very long message, very very very very very very
// very very very very very very very very very very very very very very
// very very very very very very very very very very very very very very
// very very very very very very very very very very very very very very
// very very very very very very very very very very very very very very
// long message attached to the top of it.
// This should prove how the generator handles long doc strings.
LongMessageInt int `yaml:"longMessageInt"`

// SubStruct is a struct referenced from within the parent struct.
// This should get its own section in the referenced docs.
SubStruct SomeSubStruct `yaml:"subStruct"`

// SubStructMap is a map of a known struct type.
SubStructMap map[string]SomeSubStruct `yaml:"subStructMap"`

// AnEmbeddedStruct is embedded here.
AnEmbeddedStruct

// AliasedDuration is a type alias to a duration.
AliasedDuration MyDuration `yaml:"aliasedDuration"`

// AliasDurationString is a type alias to a duration that should be documented
// as a string type.
AliasedDurationString MyDurationString `yaml:"aliasedDurationString"`

// PointerString shows that the docs gen strips the pointer (*) from the beginning
// of the type when documented.
PointerString *string `yaml:"pointerString"`

// Private should be included as a new struct, but without any documented members.
Private PrivateMembers `yaml:"private"`

// AliasedStruct is a type aliased struct
AliasedStruct AliasSubStruct `yaml:"aliasedStruct"`

// ExternalMap references and external map type outisde of the package.
ExternalMap template.FuncMap `yaml:"externalMap"`

// AliasExternalMap references an external map type outside of the package via an alias.
AliasExternalMap AliasedExternalMap `yaml:"aliasExternalMap"`

// Bytes is a slice of raw byte data.
Bytes []byte `yaml:"bytes"`
}

// SomeSubStruct is a struct to go within another struct.
type SomeSubStruct struct {
// NonTaggedField doesn't have a tag, so the name will be capitalised.
NonTaggedField bool

// privateStruct should not be included in the docs.
privateStruct PrivateMembers
}

// AliasSubStruct is an aliased struct, it will be added to the documentation with an identical
// members table as the origin struct.
type AliasSubStruct SomeSubStruct

// AnEmbeddedStruct gets embedded within other structures.
type AnEmbeddedStruct struct {
// EmbeddedDuration is a duration within an embedded struct.
EmbeddedDuration time.Duration `yaml:"embeddedDuration"`
}

// PrivateMembers only has private members so when documented, should not have a members table printed.
type PrivateMembers struct {
privateInt int64
privateBool bool
privateBytes []byte
}

// MyDuration is an alias to a duration.
type MyDuration time.Duration

// MyDuration is an alias to a duration with the type overridden as a string
// +reference-gen:alias-name=string
type MyDurationString time.Duration

// AliasedExternalMap is an alias type for a map type outside of the package.
type AliasedExternalMap template.FuncMap
16 changes: 12 additions & 4 deletions reference-gen/pkg/generator/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,19 @@ func fieldEmbedded(m types.Member) bool {

// fieldName extracts the field name from the json tag
func fieldName(m types.Member) string {
v := reflect.StructTag(m.Tags).Get("json")
v = strings.Split(v, ",")[0]
if v != "" {
return v
vj := reflect.StructTag(m.Tags).Get("json")
vj = strings.Split(vj, ",")[0]

if vj != "" {
return vj
}

vy := reflect.StructTag(m.Tags).Get("yaml")
vy = strings.Split(vy, ",")[0]
if vy != "" {
return vy
}

return m.Name
}

Expand Down
Loading