Multiline Strings with Starlark

Hello,

I’m converting my configuration from YAML to Starlark and I’ve encountered an issue with multiline strings.

In YAML I have the following pipeline step:

- name: check
  image: alpine
  pull: if-not-exists
  commands:
    - |
      if ! echo ${DRONE_COMMIT_MESSAGE} | grep -q ${DRONE_STAGE_NAME}; then
        echo ${DRONE_STAGE_NAME} build not required
        exit 78
      fi

…and I’m trying to write it in Starlark as:

return {
  'name':     'check',
  'image':    'alpine',
  'pull':     'if-not-exists',
  'commands': '''|
    if ! echo ${DRONE_COMMIT_MESSAGE} | grep -q ${DRONE_STAGE_NAME}; then
        echo ${DRONE_STAGE_NAME} build not required
        exit 78
    fi'''
}

This fails with a generic error when attempting to convert it to YAML:

$ drone starlark convert --stdout
yaml: unmarshal errors:
  line 1: cannot unmarshal !!str `|
    ...` into []string

I’ve tried various combinations of strings and escaping newlines, but none worked. If I run with --format=false, some output gets produced:

$ drone starlark convert --stdout --format=false
---
{"kind": "pipeline", "type": "docker", "name": "ctags", "platform": {"arch": "arm64", "os": "linux"}, "steps": [{"name": "submodule", "image": "plugins/git", "pull": "if-not-exists", "commands": ["git submodule update --init ${DRONE_STAGE_NAME%%-*}"]}, {"name": "check", "image": "alpine", "pull": "if-not-exists", "commands": "|\n            if ! echo ${DRONE_COMMIT_MESSAGE} | grep -q ${DRONE_STAGE_NAME}; then\n                echo ${DRONE_STAGE_NAME} build not required\n exit 78\n            fi"}]}

Is this a bug, or am I writing the multiline command in Starlark wrong?

Thank you.

I do see two things you can fix. First is that you do not need to prefix a multiple line string with | in starlark; this is only required when writing yaml. Second is the commands attribute is a string array; your example assigns a string where a string array is expected.

Thanks! That’s a very good point about commands being an array; I wrapped my string in list brackets and the error went away. The result I got was this:

commands:
  - "if ! echo ${DRONE_COMMIT_MESSAGE} | grep -q ${DRONE_STAGE_NAME}; then\n                echo ${DRONE_STAGE_NAME} build not required\n                exit 78\n            fi"

I wasn’t sure about those literal \n inside the converted string, so in the end I put it all on one line, as in:

'commands': [
  'if ! echo ${DRONE_COMMIT_MESSAGE} | grep -q ${DRONE_STAGE_NAME}; then; ' +
    'echo ${DRONE_STAGE_NAME} build not required; ' +
    'exit 78; ' +
  'fi'
  ]

…which produces:

commands:
- if ! echo ${DRONE_COMMIT_MESSAGE} | grep -q ${DRONE_STAGE_NAME}; then; echo ${DRONE_STAGE_NAME} build not required; exit 78; fi

This seems good enough for now, and I plan to look into using the context object to generate these pipelines dynamically, so these if checks my end up being replaced completely.

Thanks again for your help!