### Summary: Generates a json schema for valid GitOps yaml files, to be used with [yaml-language-server](https://github.com/redhat-developer/yaml-language-server) for IDE integration. This PR includes the actual generated file, so it can be used without running the tool. All files are in `/tools/gitops-autto-complete`, so nothing else gets affected. #### What it adds: - Complete json schema that defines valid GitOps yaml files and can be integrated with [yaml-language-server](https://github.com/redhat-developer/yaml-language-server). - Auto-completion, error checking, type checking, descriptions. - Defines all keys for osquery options/flags (based on `server/fleet/agent_options_generated.go`). - Additional validation: required keys, strings that must be enclosed in quotation marks, path support. - Additional data: descriptions from code comments, notices for fields that don't reset if null or empty. #### Limitations: - Some structs and data are duplicated into the tool and will inevitebly mismatch over time, because the structs used for gitops are not sufficient for the schema generation: - Some fields use an interface/any type that so can't be used for the schema generation. - Some important details are not encoded in the type or struct tags for gitops fields at all. - Some details (like required fields) are encoded in the Validate() interface, but the IDE integration cannot run Go code. - Doesn't work with all yaml file types used for gitops (like a yaml file that specifies multiple software packages), only the default/fleet level files. This will require having a subsection of the schema for each type of file, and some way to detect what it actually is (maybe specifying the schema in the file itself). - Requires manual setup to integrate with IDE, it's not an easy to use extension currently. #### Dependencies: - `invopop/jsonschema` reflects Fleet's GitOps structs into the schema. - `santhosh-tekuri/jsonschema/v6` validates the test fixtures against that schema. - `ghodss/yaml` decodes the fixture YAML the way fleetctl does. https://github.com/user-attachments/assets/b6ffacd0-e602-41a2-b46a-7d10300c6ea5 ## Testing - [x] QA'd all new/changed functionality manually - I have been using and working on this for the past week so it's in a pretty good state, but some descriptions or keys are probably still missing. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added GitOps YAML auto-completion powered by a comprehensive JSON Schema. * Added validation for GitOps configuration structure, supported fields, data types, required combinations, and unknown keys. * Added support for external file references using `path` and `paths` in supported sections. * Added clearer guidance for deprecated fields and special field behaviors. * **Bug Fixes** * Improved detection of incorrectly typed values and invalid configuration shapes. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
88 lines
2.9 KiB
Markdown
88 lines
2.9 KiB
Markdown
# gitops-auto-complete
|
|
|
|
Generates a JSON schema from Fleet's GitOps Go structs so
|
|
[yaml-language-server](https://github.com/redhat-developer/yaml-language-server) can
|
|
offer completion, hover docs, and validation while you write GitOps YAML.
|
|
|
|
## How to use
|
|
|
|
### Build the schema
|
|
|
|
The tool is a separate Go module, so run it from its own directory:
|
|
|
|
```bash
|
|
cd tools/gitops-auto-complete
|
|
go run . generated-schema.json
|
|
```
|
|
|
|
The argument is the output file, or omit it to print to stdout. Re-run it whenever
|
|
the relevant Fleet structs change.
|
|
|
|
### Set up with yaml-language-server
|
|
|
|
Point yaml-language-server at the generated file. It's used by Neovim, the VS Code
|
|
YAML extension, and others. There are two ways to do this:
|
|
|
|
- Map it to your GitOps files with the `yaml.schemas` setting, which maps a schema
|
|
path to file globs.
|
|
- Or add a modeline to the top of a single file:
|
|
|
|
```yaml
|
|
# yaml-language-server: $schema=/absolute/path/to/generated-schema.json
|
|
```
|
|
|
|
### Neovim and lazy.nvim example
|
|
|
|
```lua
|
|
{
|
|
"neovim/nvim-lspconfig",
|
|
dependencies = {
|
|
{ "mason-org/mason.nvim", opts = {} },
|
|
"mason-org/mason-lspconfig.nvim",
|
|
},
|
|
config = function()
|
|
vim.lsp.config("yamlls", {
|
|
settings = {
|
|
yaml = {
|
|
schemas = {
|
|
-- schema file -> which YAML files it applies to
|
|
["/absolute/path/to/generated-schema.json"] = {
|
|
"**/default.yml",
|
|
"**/teams/*.yml",
|
|
"**/fleets/*.yml",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
vim.lsp.enable("yamlls")
|
|
end,
|
|
}
|
|
```
|
|
|
|
Install the server once (`:MasonInstall yaml-language-server`), reload, and open a
|
|
GitOps file. Hover a key with `K` to see its type and docs.
|
|
|
|
## How it works
|
|
|
|
Reflects a `GitOpsSpec` struct that mirrors the real top-level GitOps keys, such as
|
|
`org_settings`, `controls`, `software`, and `policies`, reusing Fleet's own types for
|
|
each section, via [`invopop/jsonschema`](https://github.com/invopop/jsonschema). It
|
|
then post-processes the result so the schema matches how GitOps files are written:
|
|
file-path references, legacy key aliases, required fields for an item, and field docs
|
|
pulled from Go comments.
|
|
|
|
It's a separate Go module with a `replace` back to the repo, so it builds from inside
|
|
the repo without adding dependencies to the root `go.mod`.
|
|
|
|
## Known limitations
|
|
|
|
- The schema is filename-agnostic, but Fleet applies some keys differently by file.
|
|
For example, `agent_options` and `reports` are rejected in `no-team.yml` and the
|
|
unassigned file. The schema still accepts them there, so that mistake shows up at
|
|
`fleetctl` apply time, not in the editor.
|
|
- `GitOpsSpec` and `ControlsWithTypes` are hand-written mirrors of `spec.GitOps` and
|
|
`spec.GitOpsControls`, because those spec structs are untyped or untagged and reflect
|
|
poorly. `TestControlsKeysCoverSpec` catches a controls-key drift, but a new top-level
|
|
key has to be added to `GitOpsSpec` by hand, as `custom_host_vitals` was.
|