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

Add new columns "Options", "Regex", and "Mandatory" to the inputs table and improve display of empty strings and nil values #16

Merged
merged 3 commits into from
Jun 13, 2024
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
35 changes: 18 additions & 17 deletions .github/workflows/cicd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,29 +40,12 @@ jobs:
- name: "Run go build"
run: "go build"

mirror-gitlab-job:
runs-on: "ubuntu-22.04"
steps:
- name: "Check out repository"
uses: "actions/[email protected]"
with:
fetch-depth: 0
- name: "Add Gitlab Remote"
run: |
git remote add gitlab https://oauth2:${{ secrets.GITLAB_LABDOC_MIRROR_TOKEN }}@gitlab.com/erNail/labdoc.git
- name: "Push all branches to GitLab"
run: "git push gitlab --all --force"

- name: "Push all tags to GitLab"
run: "git push gitlab --tags --force"

release-job:
runs-on: "ubuntu-22.04"
needs:
- "go-test-job"
- "go-build-job"
- "pre-commit-job"
- "mirror-gitlab-job"
permissions:
contents: "write"
steps:
Expand Down Expand Up @@ -95,4 +78,22 @@ jobs:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
DOCKER_LABDOC_GORELEASER_TOKEN: "${{ secrets.DOCKER_LABDOC_GORELEASER_TOKEN }}"
HOMEBREW_TAP_ERNAIL_GITHUB_TOKEN: "${{ secrets.HOMEBREW_TAP_ERNAIL_GITHUB_TOKEN }}"

mirror-gitlab-job:
runs-on: "ubuntu-22.04"
needs:
- "release-job"
steps:
- name: "Check out repository"
uses: "actions/[email protected]"
with:
fetch-depth: 0
- name: "Add Gitlab Remote"
run: |
git remote add gitlab https://oauth2:${{ secrets.GITLAB_LABDOC_MIRROR_TOKEN }}@gitlab.com/erNail/labdoc.git
- name: "Push all branches to GitLab"
run: "git push gitlab --all --force"

- name: "Push all tags to GitLab"
run: "git push gitlab --tags --force"
...
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@ github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
Expand Down
239 changes: 183 additions & 56 deletions internal/gitlab/component_documentation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,201 @@ import (
"github.com/stretchr/testify/require"
)

func TestGenerateDocumentationUsesEmbeddedTemplate(t *testing.T) {
func TestGenerateDocumentationRendersInputTableCorrectly(t *testing.T) {
t.Parallel()

componentContent := `---
# Component Description
spec:
inputs:
string-with-default:
type: "string"
default: ""
string-without-default:
type: "string"
array-with-default:
type: "array"
default: []
array-without-default:
type: "array"
boolean-with-default:
type: "boolean"
default: false
boolean-without-default:
type: "boolean"
number-with-default:
type: "number"
default: 0
number-without-default:
type: "number"
string-with-options:
type: "string"
options:
- "one"
- "two"
string-with-regex:
type: "string"
regex: "^test."
input-with-description-only:
description: "Input with description only"
input-with-default-only:
default: []
input-without-anything: {}
...
`

expectedMarkdownTable := "\n" +
"| Name | Description | Type | Default | Options | Regex | Mandatory |\n" +
"|------|-------------|------|---------|---------|-------|-----------|\n" +
"| `array-with-default` | | `array` | `[]` | `-` | `-` | No |\n" +
"| `array-without-default` | | `array` | `-` | `-` | `-` | Yes |\n" +
"| `boolean-with-default` | | `boolean` | `false` | `-` | `-` | No |\n" +
"| `boolean-without-default` | | `boolean` | `-` | `-` | `-` | Yes |\n" +
"| `input-with-default-only` | | `-` | `[]` | `-` | `-` | No |\n" +
"| `input-with-description-only` | Input with description only | `-` | `-` | `-` | `-` | Yes |\n" +
"| `input-without-anything` | | `-` | `-` | `-` | `-` | Yes |\n" +
"| `number-with-default` | | `number` | `0` | `-` | `-` | No |\n" +
"| `number-without-default` | | `number` | `-` | `-` | `-` | Yes |\n" +
"| `string-with-default` | | `string` | `\"\"` | `-` | `-` | No |\n" +
"| `string-with-options` | | `string` | `-` | `[one two]` | `-` | Yes |\n" +
"| `string-with-regex` | | `string` | `-` | `-` | `^test.` | Yes |\n" +
"| `string-without-default` | | `string` | `-` | `-` | `-` | Yes |\n"

filesystem := afero.NewMemMapFs()
componentDir := "templates"
componentPath := componentDir + "/first-component.yml"
outputFilePath := "README.md"

err := filesystem.Mkdir(componentDir, 0o644)
require.NoError(t, err)
err = afero.WriteFile(filesystem, componentPath, []byte(componentContent), 0o644)
require.NoError(t, err)

documentationGenerator := &RealDocumentationGenerator{}
documentationGenerator.GenerateDocumentation(
filesystem,
"templates",
"resources/default-template.md.gotmpl",
"github.com/test",
"1.0.0",
"README.md",
false,
)

outputExists, err := afero.Exists(filesystem, outputFilePath)
require.NoError(t, err)
assert.True(t, outputExists)

outputContent, err := afero.ReadFile(filesystem, outputFilePath)
require.NoError(t, err)
assert.Contains(t, string(outputContent), expectedMarkdownTable)
}

func TestGenerateDocumentationRendersMultipleJobsAndComponentsCorrectly(t *testing.T) {
t.Parallel()

firstComponentContent := `---
# This is a description of the first component
# First Component
spec:
inputs:
stage:
description: "The stage of the jobs"
type: "string"
default: "test"
...
---
# This is the first job of the first component
# First Component first job
first-component-first-job: {}

# This is the second job of the first component
# First Component second job
first-component-second-job: {}
`

secondComponentContent := `---
# This is a description of the second component
# Second Component
spec:
inputs:
stage:
description: "The stage of the jobs"
type: "string"
default: "test"
...
---
# This is the first job of the second component
# Second Component first job
second-component-first-job: {}

# This is the second job of the second component
# Second Component second job
second-component-second-job: {}
...
`

expectedMarkdown := `# Components Documentation

## Components

### first-component

First Component
` +
"\n#### Usage of component `first-component`" +
"\n" +
"\nYou can add this component to an existing `.gitlab-ci.yml` file by using the `include:` keyword.\n" +
"\n" +
"```yaml\n" +
"include:\n" +
" - component: \"github.com/test/[email protected]\"\n" +
" inputs: {}\n" +
"```\n" +
`
You can configure the component with the inputs documented below.
` +
"\n#### Inputs of component `first-component`\n" +
`
| Name | Description | Type | Default | Options | Regex | Mandatory |
|------|-------------|------|---------|---------|-------|-----------|
` +
"| `stage` | | `-` | `-` | `-` | `-` | Yes |\n" +
"\n" +
"#### Jobs of component `first-component`\n" +
`
The component will add the following jobs to your CI/CD Pipeline.
` +
"\n##### `first-component-first-job`\n" +
`
First Component first job
` +
"\n##### `first-component-second-job`\n" +
`
First Component second job

### second-component

Second Component
` +
"\n#### Usage of component `second-component`" +
"\n" +
"\nYou can add this component to an existing `.gitlab-ci.yml` file by using the `include:` keyword.\n" +
"\n" +
"```yaml\n" +
"include:\n" +
" - component: \"github.com/test/[email protected]\"\n" +
" inputs: {}\n" +
"```\n" +
`
You can configure the component with the inputs documented below.
` +
"\n#### Inputs of component `second-component`\n" +
`
| Name | Description | Type | Default | Options | Regex | Mandatory |
|------|-------------|------|---------|---------|-------|-----------|
` +
"| `stage` | | `-` | `-` | `-` | `-` | Yes |\n" +
"\n" +
"#### Jobs of component `second-component`\n" +
`
The component will add the following jobs to your CI/CD Pipeline.
` +
"\n##### `second-component-first-job`\n" +
`
Second Component first job
` +
"\n##### `second-component-second-job`\n" +
`
Second Component second job
`

filesystem := afero.NewMemMapFs()
Expand Down Expand Up @@ -75,68 +235,35 @@ second-component-second-job: {}

outputContent, err := afero.ReadFile(filesystem, outputFilePath)
require.NoError(t, err)
assert.Contains(t, string(outputContent), "### first-component")
assert.Contains(t, string(outputContent), "### second-component")
assert.Contains(t, string(outputContent), "##### `second-component-second-job`")
assert.Equal(t, expectedMarkdown, string(outputContent))
}

func TestGenerateDocumentationUsesCustomTemplate(t *testing.T) {
t.Parallel()

firstComponentContent := `---
# This is a description of the first component
spec:
inputs:
stage:
description: "The stage of the jobs"
type: "string"
default: "test"
...
---
# This is the first job of the first component
first-component-first-job: {}

# This is the second job of the first component
first-component-second-job: {}
`

secondComponentContent := `---
# This is a description of the second component
componentContent := `---
# This is a custom template
spec:
inputs:
stage:
description: "The stage of the jobs"
type: "string"
default: "test"
...
---
# This is the first job of the second component
second-component-first-job: {}

# This is the second job of the second component
second-component-second-job: {}
`

customTemplateContent := `
# Components Documentation

{{ range $component := .Components }}
This is component {{ $component.Name }}
{{ end }}
`
{{- range $component := .Components }}
Description: {{ $component.Description }}
{{- end }}
`

filesystem := afero.NewMemMapFs()
componentDir := "templates"
firstComponentPath := componentDir + "/first-component.yml"
secondComponentPath := componentDir + "/second-component.yml"
componentPath := componentDir + "/first-component.yml"
outputFilePath := "README.md"
customTemplateFilePath := "my-template.yml"

err := filesystem.Mkdir(componentDir, 0o644)
require.NoError(t, err)
err = afero.WriteFile(filesystem, firstComponentPath, []byte(firstComponentContent), 0o644)
require.NoError(t, err)
err = afero.WriteFile(filesystem, secondComponentPath, []byte(secondComponentContent), 0o644)
err = afero.WriteFile(filesystem, componentPath, []byte(componentContent), 0o644)
require.NoError(t, err)
err = afero.WriteFile(filesystem, customTemplateFilePath, []byte(customTemplateContent), 0o644)
require.NoError(t, err)
Expand All @@ -157,7 +284,7 @@ second-component-second-job: {}

outputContent, err := afero.ReadFile(filesystem, outputFilePath)
require.NoError(t, err)
assert.Contains(t, string(outputContent), "This is component first-component")
assert.Contains(t, string(outputContent), "Description: This is a custom template")
}

func TestBuildComponentDocumentationFromComponentsBuildsSortedComponentDocumentation(t *testing.T) {
Expand Down
Loading
Loading