Skip to content

Add javascript code snippet validation #662

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

Merged
merged 47 commits into from
Mar 22, 2018

Conversation

ThomasHickman
Copy link
Member

This fixes #594. Note: I refractored most of exec_js (in sandbox_js) into exec_js_process, so that I could use a function that runs a javascript process, inputs the results to stdin and captures them on stdout, while having a timeout.

Fixes common-workflow-language#594. To do this, it is needed to add jshint and refractor
js_sandbox to so that it can be useful for this.
@mr-c
Copy link
Member

mr-c commented Feb 15, 2018

cwltool/linting/lint.js needs to be listed in MANIFEST.in

})
)

def dump_jshint_error():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs type information

return []

return list(itertools.chain(*
map(lambda x: get_expressions(x[1], schema.items, SourceLine(tool, x[0])), enumerate(tool))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cwltool/validate_js.py:47: error: "Schema" has no attribute "items" from https://travis-ci.org/common-workflow-language/cwltool/jobs/348306873#L618

@@ -187,7 +188,9 @@ def validate_document(document_loader, # type: Loader
fetcher_constructor=None, # type: FetcherConstructorType
skip_schemas=None, # type: bool
overrides=None, # type: List[Dict]
metadata=None, # type: Optional[Dict]
metadata=None, # type: Optional[Dict],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The extra comma at the end of the type hint needs to be removed

@mr-c
Copy link
Member

mr-c commented Mar 2, 2018

Jenkins, test this please

linter_folder = resource_filename(__name__, "jshint")

returncode, stdout, stderr = exec_js_process(
path.join(linter_folder, "jshint_wrapper.js"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here you should use get_data from https://github.com/common-workflow-language/cwltool/blob/master/tests/util.py (maybe that should be moved to the cwltool package?)

This is why the conformance tests are failing 🙂

@mr-c
Copy link
Member

mr-c commented Mar 5, 2018

@ThomasHickman You are getting closer! :-)

@ThomasHickman
Copy link
Member Author

@mr-c any idea what I'm still doing wrong? :)

@mr-c
Copy link
Member

mr-c commented Mar 5, 2018

@ThomasHickman I haven't had a chance to try myself yet, but the next stage is to create a new virtualenv, pip install this branch into it; and then execute the CWL conformance tests, debugging any failures directly.

https://github.com/common-workflow-language/common-workflow-language/blob/master/CONFORMANCE_TESTS.md#usage with RUNNER=cwltool

@mr-c
Copy link
Member

mr-c commented Mar 10, 2018

Much closer!

~/common-workflow-language/v1.0$ cwltool --debug  v1.0/template-tool.cwl v1.0/cat-job.json
/home/michael/common-workflow-language/env/bin/cwltool 1.0.20180310142018
Resolved 'v1.0/template-tool.cwl' to 'file:///home/michael/common-workflow-language/v1.0/v1.0/template-tool.cwl'
I'm sorry, I couldn't load this CWL file.  The error was:
Traceback (most recent call last):
  File "/home/michael/common-workflow-language/env/local/lib/python2.7/site-packages/cwltool/main.py", line 492, in main
    validate_js_options=validate_js_options)
  File "/home/michael/common-workflow-language/env/local/lib/python2.7/site-packages/cwltool/load_tool.py", line 288, in validate_document
    validate_js_expressions(processobj, avsc_names.names[workflowobj["class"]], validate_js_options)
  File "/home/michael/common-workflow-language/env/local/lib/python2.7/site-packages/cwltool/validate_js.py", line 170, in validate_js_expressions
    expression_lib_errors, expression_lib_globals = jshint_js("\n".join(expression_lib), default_globals, jshint_options)
  File "/home/michael/common-workflow-language/env/local/lib/python2.7/site-packages/cwltool/validate_js.py", line 112, in jshint_js
    context=jshint_functions_text
  File "/home/michael/common-workflow-language/env/local/lib/python2.7/site-packages/cwltool/sandboxjs.py", line 264, in exec_js_process
    while not process_finished() and tm.is_alive():
  File "/home/michael/common-workflow-language/env/local/lib/python2.7/site-packages/cwltool/sandboxjs.py", line 186, in process_finished
    return stdout_buf.getvalue().decode().endswith(PROCESS_FINISHED_STR) and \
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 28449: ordinal not in range(128)

@mr-c
Copy link
Member

mr-c commented Mar 10, 2018

Thanks again @ThomasHickman ; this is working everywhere but Windows. Ping me once that is fixed I'll do a final review and we can get this merged!

@ThomasHickman
Copy link
Member Author

@mr-c I've fixed the windows issue. Do you want to do a final review now?

Note from above: I've removed the get_data to get_test_data change as I don't need get_data in cwltool.utils and this change affects a lot of files

@tetron
Copy link
Member

tetron commented Mar 12, 2018

The reason for using resource_stream is to support delivery as a Python egg. Assuming files are on disk doesn't work when the module is stored in a zip archive (I don't know if wheels have similar behavior.)

@mr-c
Copy link
Member

mr-c commented Mar 12, 2018 via email

@tetron
Copy link
Member

tetron commented Mar 12, 2018

So if we want to be clever about it, the wrapper method should try resource_stream() first and then fall back to searching for the file?

@ThomasHickman
Copy link
Member Author

ThomasHickman commented Mar 12, 2018

@tetron yes, this is already implemented in the util file in the tests folder:

def get_data(filename):
Also, if we are going to modify all resource_stream functions such that you can run code in place, wouldn't it be better to implement that in a separate PR?

@mr-c
Copy link
Member

mr-c commented Mar 12, 2018 via email

@tetron
Copy link
Member

tetron commented Mar 12, 2018

A few comments -

  • Consider moving the call to JS validation out of load_tool and into Process.__init__(), that's where other secondary validation (input/output port type checking) currently happens.
  • It looks like get_expressions traverse the schema and tool record in parallel. This is a good strategy but somewhat expensive, a simpler/faster strategy would be to walk the schema once to determine the set of fields that are permitted to contain expressions, and then walk the tool object searching for those fields.
  • If jshint finds an obvious error (syntax error, for example) it should raise a ValidationException

However I don't want to hold up merging a useful feature on these, if @mr-c has tested it and it seems to be working well, I'm okay with merging now and doing a followup cleanup PR.

@ThomasHickman
Copy link
Member Author

@tetron Those seem fair enough comments. I also noticed while having a look at (1) that command line parameters were not getting propagated to validate_js in load_tool - the best way to solve this is to implement point (1), so this is done above

@mr-c
Copy link
Member

mr-c commented Mar 12, 2018

As before, as long as follow up issues are filed so we don't completely forget them I'm fine merging this now 😁

@codecov-io
Copy link

codecov-io commented Mar 22, 2018

Codecov Report

Merging #662 into master will increase coverage by 0.17%.
The diff coverage is 68.53%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #662      +/-   ##
==========================================
+ Coverage    62.4%   62.57%   +0.17%     
==========================================
  Files          26       27       +1     
  Lines        4274     4414     +140     
  Branches     1147     1180      +33     
==========================================
+ Hits         2667     2762      +95     
- Misses       1324     1358      +34     
- Partials      283      294      +11
Impacted Files Coverage Δ
cwltool/load_tool.py 81.25% <ø> (ø) ⬆️
cwltool/argparser.py 80.88% <100%> (+0.18%) ⬆️
cwltool/process.py 67.93% <36.36%> (-0.62%) ⬇️
cwltool/sandboxjs.py 43.91% <54.83%> (-0.27%) ⬇️
cwltool/validate_js.py 79.61% <79.61%> (ø)
cwltool/executors.py 68.57% <0%> (-2.86%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b1f9024...1786a7f. Read the comment docs.

@tetron tetron merged commit 9564713 into common-workflow-language:master Mar 22, 2018
@mr-c
Copy link
Member

mr-c commented Mar 22, 2018

@ThomasHickman @tetron Please file follow up issues as requested

@tetron
Copy link
Member

tetron commented Mar 22, 2018

@mr-c #699 were there any others?

@ThomasHickman ThomasHickman deleted the js-linting branch March 22, 2018 20:13
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

Successfully merging this pull request may close these issues.

cwltool --validate should validate that javascript expressions are valid ES5 expressions
4 participants