CircleCI-Public / circleci-yaml-language-server

The official language server for CircleCI YAML configuration files
Apache License 2.0
20 stars 18 forks source link

fix: remove parsing error for local orbs #273

Closed JulesFaucherre closed 8 months ago

JulesFaucherre commented 8 months ago

Jira

Description

Fix BIG errors in local orb parsing. Because of this bug, local orb parsing was crashing because when there more than one type of entity declared. For example, you could not declare a local orb that would declare both jobs and commands.

Implementation details

To parse a local orbs, you get the content of the local and give it to the function that parses YAML file. Let's take an example YAML:

orbs:
  local-orb:
    commands:
      command:
        steps:
          - run: echo hello world
    jobs:
      job:
        docker:
          - image: cimg/base:2024.01
        steps:
          - command

To parse local-orb, the code will take the tree-sitter node that represent the orb, get its content and parse it like any other YAML. One minor adjustment needs to be done to make sure everything works in order: all the ranges parsed in the orb must be offset to the actual position of the orb, to keep the ranges in sync. For our example, since the orb starts at line 2 character 4, we must add 2 to the Line values of the range coming out of the parser. For the character 4 part though, since your orb's YAML is actually a map, and that you can offset a map by any number of space as long it's consistent for all keys, we thought we could ignore it... Until now. Why? Because let's fmt.Println the content of local-orb:

commands:
      command:
        steps:
          - run: echo hello world
    jobs:
      job:
        docker:
          - image: cimg/base:2024.01
        steps:
          - command

The issue here is pretty clear, isn't it? We may ignore the offset as it's gonna stay the for all lines, but we got to make sure the first line have this same offset too... And unfortunately it did not. This caused the parsing of local orbs to work well when there was only one "top-level" declaration, because you have only a one-key map, but to crash as soon as you add anything else to the map.

This PR thus adds the said offset to the first line of the orb

    orbContent := strings.Repeat(" ", int(orbRange.Start.Character)) + doc.GetNodeText(orbNode)

which resolves the issue.

How to validate

A test has been added, but for in-editor testing, feel free to use any file you'd like, I used this:

version: 2.1

orbs:
  local:
    commands:
      cmd:
        parameters:
          target:
            type: string
        steps:
          - run: echo << parameters.target >>
    jobs:
      job:
        docker:
          - image: cimg/node:21.6.1
        steps:
          - cmd:
              target: world

jobs:
  do:
    docker:
      - image: cimg/node:21.6.1
    steps:
      - local/cmd:
          target: world

workflows:
  act:
    jobs:
      - do
      - local/job