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

Build job with files. #73

Closed
binoyudayan opened this issue Dec 9, 2022 · 10 comments
Closed

Build job with files. #73

binoyudayan opened this issue Dec 9, 2022 · 10 comments

Comments

@binoyudayan
Copy link

Hi

Currently the job.py/Project.build is only accepting parameters, this doesn't include any file parameter. Even if we pass a file parameter, this won't be properly mapped to requests file parameter. So, either we need to separate the file from params and pass it to self.handle_req method in build method. But this may create a conflict if the job already has a parameter named file. The following method does the job, but duplicates part of job.py/Project.build

def build_job_with_files(self, files: dict, **params) -> QueueItem:
    """
    same function from api4jenkins.job.Project.build. Added files additionally.
    :param files: dict of all file inputs with field name and file object like {'jsonfile': <fp>}
    :param params: build params
    """
    reserved = ['token', 'delay']
    if not params or all(k in reserved for k in params):
        entry = 'build'
    else:
        entry = 'buildWithParameters'
    resp = self.handle_req('POST', entry, params=params, files=files)
    return QueueItem(self, resp.headers['Location'])

Please let me know your comment, I can make PR with your suggestions if you think this make sense.

@joelee2012
Copy link
Owner

@binoyudayan thanks for reporting the issue, i prefer to separate files from params and record in docment

@binoyudayan
Copy link
Author

hi @joelee2012 ,
You meant get files from params(params.get('files')) and then put the files in resp = self.handle_req('POST', entry, params=params, files=files) in build method itself instead of having a new method?

@joelee2012
Copy link
Owner

@binoyudayan not really, i mean extract parameter if its value starts with @, then construct files parameter for requests

@praczyns
Copy link

praczyns commented Mar 29, 2023

Hi @binoyudayan have you managed to send a PR with that? It'd be very useful to be able to create job with file parameter.

@binoyudayan
Copy link
Author

@praczyns Sorry, I haven't worked on it yet. But I can make a PR.
@joelee2012 Sorry for the late response. But I really didn't get what you mean by this 'extract parameter if its value starts with @, then construct files parameter for requests'

@praczyns
Copy link

Thanks, I'm not sure either.

However what I did is I included files as on of the variable length parameters (**params) to build_job, then inside Job build, if 'files' key is in the params dict, I pop it from the dict and pass as files parameter to requests post and pass the rest of the parameters via params. Not super clean as it restricts files from being used as a normal job parameter name but works and it's minimal changes to the library.

I guess what @joelee2012 meant was something between these lines but to also use @ (@files) to distinguish the key as special value?

However I'm affraid that won't work with variable length parameters as AFAIK you cannot have parameter with @ prefix (but you can have dict key starting with @)

@binoyudayan
Copy link
Author

@praczyns Passing the files key in the params dict will solve the problem. files parameter must be a dictionary I guess to have multiple files. As you have mentioned, this is not clean implementation as this restrict the user from using files key for any other parameter.

Other option is to check the value of each parameter value is file-like and then add them to the files parameter in the post request.

@joelee2012
Copy link
Owner

joelee2012 commented Mar 31, 2023

@binoyudayan @praczyns my idea is to check value of parameter start with '@' then add them to files parameter, here is snippet

def build(self, **params):
    reserved = ['token', 'delay']
    if not params or all(k in reserved for k in params):
        entry = 'build'
    else:
        entry = 'buildWithParameters'
    # collect file parameter if its value start with '@'
    all_files = []
    for k, v in params.items():
        if v[0] == '@':
            all_files.append((k, ('v[1:]', open('v[1:]', 'rb'))))

    # remove file from paramters
    for file in all_files:
        params.pop(file[0])

    try:
        resp = self.handle_req('POST', entry, params=params, files=all_files)
    finally:
        # eusure file be closed
        for file in all_files:
            file[1][1].close()

    return QueueItem(self.jenkins, resp.headers['Location'])

but i think @binoyudayan 's idea to check file-like is better, how do you think ? and @binoyudayan are you able to make PR ?

@binoyudayan
Copy link
Author

@joelee2012 sure, I can work on that.

@joelee2012
Copy link
Owner

As described in https://issues.jenkins.io/browse/JENKINS-47333, Jenkins will not support file parameter, and there is no https://www.jenkins.io/doc/book/pipeline/syntax/#parameters either

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

No branches or pull requests

3 participants