Using go-c8y-cli in Azure DevOps Pipeline

Product/components used and version:

  • Azure DevOps runners
    • Hosted latest Ubuntu
    • Self-hosted on Azure VM Ubuntu 2204
  • go-c8y-cli version: 2.44.2
  • PowerShell version: 7.4.6

Detailed explanation of the problem:

Running a simple pipeline to get a list of c8y extensions.
The pipeline completes below command to create session and activate session fine:

  • c8y sessions create --host 'https://${{ parameters.c8yTenantHostName }}' --username '$(c8y_devops_username)' --password '$(c8y_devops_password)' --type dev
  • c8y sessions set --shell powershell | Out-String | Invoke-Expression

But it hangs forever on below command to list c8y extensions:

  • c8y ui plugins list --name "${{ parameters.extensionName }}" --debug
Investigation:

When I connect to the VM via SSH and ran the exactly the same command as pipeline ran, it completes fine and activity log has all the GET and PUT request entries as well.

Just wondering if anyone has experienced this before or any idea?

Error messages / full error message screenshot / log file:

  • Hanging in pipeline

  • Activity log (/home/AzDevOps/.cumulocity/activitylog/c8y.activitylog.2024-12-04.json)

    {"time":"2024-12-04T00:34:03.129524038Z","ctx":"vFoLjGXV","type":"command","arguments":["sessions","set","--shell","powershell"]}
    {"time":"2024-12-04T00:34:05.049707224Z","ctx":"SlWTDGap","type":"command","arguments":["ui","plugins","list","--name","xxx","--debug"]}
    
  • When I connect to the VM via SSH and ran the exactly the same command, it completes fine

Question related to a free trial, or to a production (customer) instance?

Production

CI runners such as Azure DevOps, Github Runner etc, seem to do some strange things with standard input (stdin) which makes go-c8y-cli think there is always piped data coming in, and it continuously tries to read from it.

Unfortunately I have not yet found a nice ways to automatically detect this, so you’ll need to add an additional global flag (-n or the long form --nullInput) to each command which is not expecting piped input.

For example, the command you listed should be:


c8y ui plugins list -n --name "${{ parameters.extensionName }}" --debug

But if you are using a pipeline, then the -n or --nullInput only needs to be added to the first command, as the second is getting info from the pipeline.


c8y applications list -n | c8y applications update --template "{}"

This isn’t the first time this has come up, so I’m thinking I should create a dedicated CI section in the go-c8y-cli docs.

But there are a few hints in the docs in various places (but no so obvious if you’re looking at doing CI stuff):

c8y automatically detects and reads from standard input. When using read inside a loop, it will write to standard input, c8y will intercept the input and the loop will only be run once instead of once per line.

To get around this, use the -n/–nullInput parameter. This parameter will disable reading from standard input.

Interesting enough, cronjobs are also affected by this as cronjobs inject an empty space to the stdin when running scripts. But this can be mitigated by redirecting /dev/null

Documentation references

1 Like

Thanks very much @Reuben_Miller2. It’s all working in Azure DevOps now.
And a CI section would be nice.