Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return stdout of command #11

Closed
g3n35i5 opened this issue Dec 29, 2022 · 10 comments · Fixed by jfrog/jenkins-jfrog-plugin#113
Closed

Return stdout of command #11

g3n35i5 opened this issue Dec 29, 2022 · 10 comments · Fixed by jfrog/jenkins-jfrog-plugin#113
Labels
feature request New feature or request

Comments

@g3n35i5
Copy link

g3n35i5 commented Dec 29, 2022

Is your feature request related to a problem? Please describe.

I'm trying to evaluate whether an artifact already exists on the repository I'm trying to upload to. To do so, I thought of using the jf rt search command, but as far as I can see, the the function is a void function.

Describe the solution you'd like to see

Return stdout of executed command so that it can be stored/interpreted in the following way (Jenkins declarative pipeline example):

script {
    String result = jf 'rt search --count <repository>/<file>'
    echo result
}

Describe alternatives you've considered

Since the jf execution is printed to the job's log, I could parse the log instead (or at least the last N lines). But this approach seems to be very hacky...

@g3n35i5 g3n35i5 added the feature request New feature or request label Dec 29, 2022
@g3n35i5 g3n35i5 changed the title Return stdout/stderr of command Return stdout of command Dec 29, 2022
@g3n35i5
Copy link
Author

g3n35i5 commented Dec 29, 2022

I reduced the scope to the stdout of the command since I know that Jenkins doesn't really support handling the stderr of command executions.

@john-heinnickel
Copy link

+1 here with another use case description in case it either (a) helps rationalize and scope the feature, or (b) leads to a recommended workaround.

A running Pipeline job needs to either execute a job step if that job it would activate has not yet built the head commit of a branch. The Pipeline knows (1) the build name that the job will use to publish, (2) the GitHub repo it builds from, and (3) the branch it builds from, but it cannot accurately predict the latest build number.
The goal is to use a jf rt search execution to read @vcs.commit from an item with the largest @build.number with @build.name == (1), then use the git client to determine if that @vcs.commit property value is the head of (3) on (2) or merely an ancestor of the head. In the former case, take a shortcut by skipping the job step, and in the latter case, include it in the critical path.

  • If sorting by @build.number and reading only the first row works, this is done in one jf CLI call, but needs to read the output in order to know the @vcs.property` needed to query Git
  • If a sort and limit approach won't work, a jf rt curl /api/builds/${1} that uses jq to parse out the first returned build number can retrieve the largest build number value for use with a $eq condition on @build.number. This requires two jf calls, both of which need to have access to the command's output.

Seems unfortunate that the CLI has no --output argument to direct it to send output to a specific destination. I suppose that would be redundant with shell redirection but would allow solving this use case without changing the return type, although I'd much rather see an option like sh's returnStdout keyword argument, if only because it does not require a disk write or mkfifo to avoid writing to disk.

@john-heinnickel
Copy link

Does anyone happen to know where Jenkins' code base keeps the implementation of built-in steps like sh?

I'm not aware of any steps other than sh that have a behavioral toggle that determines whether their standard out goes to the console channel or becomes a return value from the step, do I'm not aware of any other call signature contracts for this kind of behavior. But given the existence of one precedent contract, I imagine it makes sense to expose similar functionality with the same contract.

If that's true, then it might be relatively straightforward to pitch a PR by following that sh's implementation as an example, but I seem to be looking for a needle in a haystack to that end...

@g3n35i5
Copy link
Author

g3n35i5 commented Jan 5, 2023

Does anyone happen to know where Jenkins' code base keeps the implementation of built-in steps like sh?

I have also been looking for ages but unfortunately never found it. Should you be more successful in the search I would be very happy about the info 😄

I'm not aware of any steps other than sh that have a behavioral toggle that determines whether their standard out goes to the console channel or becomes a return value from the step

AFAIK, you always must do a "switch case" depending on the runner OS, e.g. for windows it is bat and not sh. But these APIs also support returning stdout.

Edit
A quick search here in the source code showed that Jenkins does the execution of with a Launcher.ProcStarter. The way I see it, the API seems to be OS-independent (and apparently even provides support for stderr).

@zphixon
Copy link

zphixon commented Feb 14, 2023

We're using a tee step and setting the JFROG_CLI_LOG_LEVEL to ERROR but it's still including a line like in the file like

[***] $ /***/tools/io.jenkins.plugins.jfrog.JfrogInstallation/JFrog_CLI/jf rt build-publish --dry-run=true

which isn't valid JSON lol. We're skipping over that line for now, but it is indeed an awful hack. Support for this use case would be very nice.

@wxm809
Copy link

wxm809 commented Jul 3, 2024

Seconding this PR. Would find this feature very useful for my purposes.

@nickheyer
Copy link

I assumed this "feature" would be among the most basic criteria for a plugin like this, but apparently it wasn't ever a requirement to assert the output of the command itself?

What this plugin is in it's current state: A "jf-cli installer" distribution plugin w/ a poorly implemented sh wrapper around the installed binary. It's not durable, it's unable to parse strings properly, it attempts to install the jf-cli package wherever it is invoked in a child stage even on the same node, it's documentation is mostly pointless and provides no examples beyond the same shell commands in the jf docs (but now your output is nullified), it presumptuously injects details into your build artifacts on upload (based on whichever stage the command was issued in)... I could go on.

This needs work.

@yahavi
Copy link
Collaborator

yahavi commented Nov 9, 2024

@g3n35i5 @zphixon @john-heinnickel @nickheyer @wxm809
Thank you for using the Jenkins JFrog plugin. We have created jfrog#113 to support this feature.

The syntax remains the same as suggested in this issue:

script {
    String result = jf 'rt search --count <repository>/<file>'
    echo result
}

To clarify – whether or not the output is captured, it will still be logged in the job output. Please let us know if this behavior is not optimal for you.

@nickheyer
Thank you very much for your valuable feedback! ❤
You mentioned several areas for improvement in this plugin:

  • It lacks durability
  • It is unable to parse strings properly
  • It attempts to install the jf-cli package wherever it is invoked within a child stage, even on the same node
  • The documentation is insufficient and provides no examples beyond the same shell commands found in the JFrog documentation
  • It presumptuously injects details into your build artifacts upon upload

Could you please elaborate on each point in as much detail as possible? Your input is invaluable for us in implementing these enhancements. If possible, please open a new issue for each one at https://github.com/jfrog/jenkins-jfrog-plugin/issues.

@deekue
Copy link

deekue commented Nov 20, 2024

@yahavi thanks for fixing this. is there a new release/tag planned that includes this fix?

@yahavi
Copy link
Collaborator

yahavi commented Dec 20, 2024

@deekue @zphixon @g3n35i5 @nickheyer

The Jenkins JFrog plugin version 1.5.7 has been released. This version allows capturing the JFrog CLI output. Here's the syntax:

script {
    String version = jf '-v'
    echo "JFrog CLI version output: $version"
}

You can learn more about this feature in the documentation: Capturing the output of JFrog CLI commands.

Feel free to upgrade, and we would appreciate your feedback on this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants