Разбор списка ключей/значений Bitrise YAML в виде структур Go

В настоящее время я работаю над шагом рабочего процесса Bitrise, и я пытаюсь разрешить этот шаг, чтобы дать пользователю возможность предоставить список необязательных пар ключ/значение YAML для ввода определенного шага, который в настоящее время пытается реализовать как:

my_step@1:
    inputs:
        - uri_actions:
            - button_text: Some text
              uri: www.google.com
            - button_text: Some text 2
              uri: www.google2.com
            - button_text: Some text 3
              uri: www.google3.com

а затем пытаемся разобрать в Go как структуры:

type config struct {
    UriActionList []UriAction `env:"uri_actions"`
}

type UriAction struct {
    ButtonText string `env:"button_text"`
    Uri        string `env:"uri"`
}

а также пытались сопоставить структуру config как варианты

type config struct {
    UriActionList map[UriAction]string `env:"uri_actions"`
}

Шаг Bitrise использует stepconf для автоматического анализа рабочего процесса пользователей и сопоставления YAML с объявленным structs:

func main() {
  var cfg config
  if err := stepconf.Parse(&cfg); err != nil {
      fmt.Fprintf(os.Stderr, "Error: %s\n", err)
      os.Exit(1)
  }
  stepconf.Print(cfg)
}
 

Но ни один из них не играет хорошо вообще ..

Это мое первое знакомство с Go и разработка собственного шага Bitrise, так что же я делаю не так? Или есть более цивилизованный способ добиться этого?


person jamie1192    schedule 06.01.2021    source источник


Ответы (2)


РЕДАКТИРОВАТЬ: Согласно обсуждению в комментариях, этот вопрос связан с библиотекой go-steputils/stepconf для анализа yaml. Но эта библиотека вообще не работает с файлами yaml и просто анализирует среду с некоторым сахаром для обработки коллекций (см. Использование библиотеки пример и тест). Я предполагаю, что где-то есть какая-то сантехника, которая преобразует yaml в переменные env.

Если вы собираетесь читать yaml из файла без этой сантехники, я бы рекомендовал использовать для этой цели хорошо документированную библиотеку - go-yaml в следующем примере:

type config struct {
    Inputs []Inputs `yaml:"inputs"`
}

type Inputs struct {
    UriActionList []UriAction `yaml:"uri_actions"`
}

type UriAction struct {
    ButtonText string `yaml:"button_text"`
    Uri        string `yaml:"uri"`
}

func main() {
    cfg := config{}

    err := yaml.Unmarshal([]byte(data), &cfg)
    if err != nil {
        log.Fatalf("error: %v", err)
    }
    fmt.Printf("---\n%v\n", cfg)
}

Игровую площадку с рабочим кодом смотрите здесь

person blami    schedule 06.01.2021
comment
Ах, извините, я должен был добавить, что в настоящее время я использую stepconf для анализа файла bitrise.yml. Функция разбора: if err := stepconf.Parse(&cfg); err != nil { fmt.Fprintf(os.Stderr, "Error: %s\n", err) os.Exit(1) - person jamie1192; 06.01.2021
comment
Я не знаком с stepconf Позвольте мне взглянуть и соответствующим образом изменить свой ответ. - person blami; 06.01.2021
comment
Похоже, что эта библиотека вообще не работает с YAML. Он анализирует переменные среды в соответствии с тем, что я вижу в их (недокументированном) коде. Если вы действительно хотите просто прочитать файл YAML и не заботиться об этой сантехнике, я бы все равно использовал go-yaml. Но я понимаю, что это может быть уже не ответ на вопрос. Я обновил свой ответ, чтобы отразить это. - person blami; 06.01.2021
comment
хм, да, похоже, это так ... только что нашел это в документации по шагам Bitrise, в которой говорится, что входные значения Step являются строками: CLI Bitrise предоставляет входные данные Step как переменные среды для шагов. devcenter.bitrise.io/contributors /create-your-own-step/ Итак, исходя из этого, кажется, что я не смогу вложить сопоставление потока YAML во входное значение.. :/ - person jamie1192; 07.01.2021

Входными данными шага могут быть только строки/тексты, поскольку они передаются шагам как переменные среды, а переменные среды могут быть только текстами. Конечно, вы можете включить в строку структуру yml, но это все равно должна быть строка.

Итак, вместо вашего оригинала

my_step@1:
    inputs:
        - uri_actions:
            - button_text: Some text
              uri: www.google.com
            - button_text: Some text 2
              uri: www.google2.com
            - button_text: Some text 3
              uri: www.google3.com

сделать значение uri_actions строкой (через |):

my_step@1:
  inputs:
    - uri_actions: |
        - button_text: Some text
          uri: www.google.com
        - button_text: Some text 2
          uri: www.google2.com
        - button_text: Some text 3
          uri: www.google3.com

затем на вашем шаге вы можете прочитать переменную среды uri_actions, которая будет содержать значение (в виде строки):

- button_text: Some text
  uri: www.google.com
- button_text: Some text 2
  uri: www.google2.com
- button_text: Some text 3
  uri: www.google3.com

Если вы хотите проанализировать это как YML, вы можете сделать это так, как упомянул @blami:

uriActionsUserInput := os.Getenv("uri_actions")
cfg := []UriAction{}
err := yaml.Unmarshal([]byte(uriActionsUserInput), &cfg)

См. полный пример здесь: https://play.golang.org/p/qst3oVnjK0X.

person Viktor Benei    schedule 09.01.2021