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

Multiple Charts, Subcharts and multiple Values file support #58

Merged
merged 6 commits into from
Feb 3, 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
2 changes: 1 addition & 1 deletion .github/workflows/artifacts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: build
run: |
make build-release
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ jobs:
steps:

- name: Install Go
uses: actions/setup-go@v2
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}

- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Lint
run: make lint
32 changes: 30 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- "master"
pull_request:
types: [synchronize]

jobs:

Expand All @@ -18,12 +19,39 @@ jobs:
steps:

- name: Install Go
uses: actions/setup-go@v2
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}

- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Run tests
run: make test

tests-windows:
name: tests
strategy:
matrix:
go-version: [1.19.1]
os: [windows-2019]
runs-on: ${{ matrix.os }}
steps:

- name: Install Go
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}

- name: Set up MinGW
uses: egor-tensin/setup-mingw@v2
with:
version: 12.2.0

- name: Checkout code
uses: actions/checkout@v4

- name: Run tests
run: make test
env:
CC: "cc"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
/bin
/dist
__debug_bin*
.vscode
.coverage
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export GOBIN?=$(BIN)
export GO=$(shell which go)
export PACKAGE_NAME=github.com/mrjosh/helm-ls
export GOLANG_CROSS_VERSION=v1.20.6
export CGO_ENABLED=1

$(eval GIT_COMMIT=$(shell git rev-parse --short HEAD))
$(eval BRANCH_NAME=$(shell git symbolic-ref -q --short HEAD || git describe --tags --exact-match))
Expand Down Expand Up @@ -57,6 +58,9 @@ install-metalinter:
test:
@$(GO) test ./... -v -race

coverage:
@$(GO) test -coverprofile=.coverage ./internal/... && go tool cover -html=.coverage

.PHONY: build-release
build-release:
@docker run \
Expand Down
22 changes: 17 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ Helm-ls is a [helm](https://github.com/helm/helm) language server protocol [LSP]
* [Make it executable](#make-it-executable)
* [Integration with yaml-language-server](#integration-with-yaml-language-server)
* [Configuration options](#configuration-options)
* [LSP Server](#lsp-server)
* [General](#general)
* [Values Files](#values-files)
* [yaml-language-server config](#yaml-language-server-config)
* [Default Configuration](#default-configuration)
* [Editor Config examples](#editor-config-examples)
Expand Down Expand Up @@ -93,10 +94,16 @@ kind: ScaledObject

You can configure helm-ls with lsp workspace configurations.

### LSP Server
### General

- **Log Level**: Adjust log verbosity.

### Values Files

- **Main Values File**: Path to the main values file (values.yaml per default)
- **Lint Overlay Values File**: Path to the lint overlay values file, which will be merged with the main values file for linting
- **Additional Values Files Glob Pattern**: Pattern for additional values files, which will be shown for completion and hover

### yaml-language-server config

- **Enable yaml-language-server**: Toggle support of this feature.
Expand All @@ -116,19 +123,24 @@ You can configure helm-ls with lsp workspace configurations.
```lua
settings = {
['helm-ls'] = {
logLevel = "debug",
logLevel = "info",
valuesFiles = {
mainValuesFile = "values.yaml",
lintOverlayValuesFile = "values.lint.yaml",
additionalValuesFilesGlobPattern = "values*.yaml"
},
yamlls = {
enabled = true,
diagnosticsLimit = 50,
showDiagnosticsDirectly = false,
path = "yaml-language-server",
config = {
schemas = {
kubernetes = "**",
kubernetes = "templates/**",
},
completion = true,
hover = true,
-- any other config: https://github.com/redhat-developer/yaml-language-server#language-server-settings
-- any other config from https://github.com/redhat-developer/yaml-language-server#language-server-settings
}
}
}
Expand Down
11 changes: 9 additions & 2 deletions cmds/lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"

"github.com/mrjosh/helm-ls/internal/charts"
locallsp "github.com/mrjosh/helm-ls/internal/lsp"
"github.com/spf13/cobra"
"go.lsp.dev/uri"
Expand All @@ -14,12 +15,18 @@ func newLintCmd() *cobra.Command {
Use: "lint",
Short: "Lint a helm project",
RunE: func(cmd *cobra.Command, args []string) error {

if len(args) == 0 {
args = append(args, os.Getenv("PWD"))
}

msgs, err := locallsp.GetDiagnostics(uri.New(args[0]))
rootPath := uri.File(args[0])
chartStore := charts.NewChartStore(rootPath, charts.NewChart)
chart, err := chartStore.GetChartForURI(rootPath)
if err != nil {
return err
}

msgs, err := locallsp.GetDiagnostics(rootPath, chart.ValuesFiles.MainValuesFile.Values)
if err != nil {
return err
}
Expand Down
1 change: 0 additions & 1 deletion internal/adapter/fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ func (fs *FileStorage) Canonical(path string) string {
}

func (fs *FileStorage) FileExists(path string) (bool, error) {

fi, err := fs.fileInfo(path)
if err != nil {
return false, err
Expand Down
6 changes: 3 additions & 3 deletions internal/adapter/yamlls/trimTemplate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,12 +307,12 @@ func TestTrimTemplate(t *testing.T) {
func testTrimTemplateWithTestData(t *testing.T, testData TrimTemplateTestData) {
doc := &lsplocal.Document{
Content: testData.documentText,
Ast: lsplocal.ParseAst(testData.documentText),
Ast: lsplocal.ParseAst(nil, testData.documentText),
}

var trimmed = trimTemplateForYamllsFromAst(doc.Ast, testData.documentText)
trimmed := trimTemplateForYamllsFromAst(doc.Ast, testData.documentText)

var result = trimmed == testData.trimmedText
result := trimmed == testData.trimmedText

if !result {
t.Errorf("Trimmed templated was not as expected but was %s ", trimmed)
Expand Down
57 changes: 57 additions & 0 deletions internal/charts/chart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package charts

import (
"github.com/mrjosh/helm-ls/internal/log"
"github.com/mrjosh/helm-ls/internal/util"
"go.lsp.dev/uri"
)

var logger = log.GetLogger()

type Chart struct {
ValuesFiles *ValuesFiles
ChartMetadata *ChartMetadata
RootURI uri.URI
ParentChart ParentChart
}

func NewChart(rootURI uri.URI, valuesFilesConfig util.ValuesFilesConfig) *Chart {
return &Chart{
ValuesFiles: NewValuesFiles(rootURI,
valuesFilesConfig.MainValuesFileName,
valuesFilesConfig.LintOverlayValuesFileName,
valuesFilesConfig.AdditionalValuesFilesGlobPattern),
ChartMetadata: NewChartMetadata(rootURI),
RootURI: rootURI,
ParentChart: newParentChart(rootURI),
}
}

type QueriedValuesFiles struct {
Selector []string
ValuesFiles *ValuesFiles
}

// ResolveValueFiles returns a list of all values files in the chart
// and all parent charts if the query tries to access global values
func (c *Chart) ResolveValueFiles(query []string, chartStore *ChartStore) []*QueriedValuesFiles {
ownResult := []*QueriedValuesFiles{{Selector: query, ValuesFiles: c.ValuesFiles}}
if len(query) == 0 {
return ownResult
}

parentChart := c.ParentChart.GetParentChart(chartStore)
if parentChart == nil {
return ownResult
}

if query[0] == "global" {
return append(ownResult,
parentChart.ResolveValueFiles(query, chartStore)...)
}

chartName := c.ChartMetadata.Metadata.Name
extendedQuery := append([]string{chartName}, query...)
return append(ownResult,
parentChart.ResolveValueFiles(extendedQuery, chartStore)...)
}
70 changes: 70 additions & 0 deletions internal/charts/chart_for_document.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package charts

import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/mrjosh/helm-ls/pkg/chartutil"
lsp "go.lsp.dev/protocol"
"go.lsp.dev/uri"
)

func (s *ChartStore) GetChartForDoc(uri lsp.DocumentURI) (*Chart, error) {
chart := s.getChartFromCache(uri)
if chart != nil {
return chart, nil
}

chart, err := s.getChartFromFilesystemForTemplates(uri.Filename())
s.Charts[chart.RootURI] = chart
if err != nil {
return chart, ErrChartNotFound{
URI: uri,
}
}
return chart, nil
}

func (s *ChartStore) getChartFromCache(uri lsp.DocumentURI) *Chart {
for chartURI, chart := range s.Charts {
if strings.HasPrefix(uri.Filename(), filepath.Join(chartURI.Filename(), "template")) {
return chart
}
}
return nil
}

func (s *ChartStore) getChartFromFilesystemForTemplates(path string) (*Chart, error) {
directory := filepath.Dir(path)
if filepath.Base(directory) == "templates" {
templatesDir := directory
expectedChartDir := filepath.Dir(templatesDir)

// check if Chart.yaml exists
if isChartDirectory(expectedChartDir) {
return s.newChart(uri.File(expectedChartDir), s.valuesFilesConfig), nil
}
}

rootDirectory := s.RootURI.Filename()
if directory == rootDirectory || directory == path {
return s.newChart(uri.File(directory), s.valuesFilesConfig), ErrChartNotFound{}
}

return s.getChartFromFilesystemForTemplates(directory)
}

func isChartDirectory(expectedChartDir string) bool {
_, err := os.Stat(filepath.Join(expectedChartDir, chartutil.ChartfileName))
return err == nil
}

type ErrChartNotFound struct {
URI lsp.DocumentURI
}

func (e ErrChartNotFound) Error() string {
return fmt.Sprintf("Chart not found for file: %s. Using fallback", e.URI)
}
Loading
Loading