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

Python deps setup #155

Merged
merged 18 commits into from
Oct 5, 2020
Merged

Python deps setup #155

merged 18 commits into from
Oct 5, 2020

Conversation

Daverlo
Copy link
Contributor

@Daverlo Daverlo commented Aug 20, 2020

Here I'm adding the support for the auto-install python dependancies. The PR adds the necessary scripts to the python-setup folder. The scripts were developed by @RasmusWL

This process is done in two steps, in the init action we install the necessary tools and try to get the dependencies, in the analyse step we configure the python extractor so it is able to find them.

The whole init process is not done in the runner as we don't want our cli to be messing around with things in the system. For the self hosted runners we don't try to install the tools for similar reasons, but we do try to get the dependencies, and that should work as long as the tools are present in the system.

There is a possibility of disabling this process by setting the input setup-python-dependencies to false.

The dependencies can be installed manually, and by providing the CODEQL_PYTHON env var in the analyse step the extractor should be able to pick them up. That en var should contain the path to the python executable that has access to the dependencies.

This comment contains more details about the different usage possibilities: https://github.com/github/codeql-python-team/issues/103#issuecomment-663252898

Merge / deployment checklist

  • Confirm this change is backwards compatible with existing workflows.
  • Confirm the readme has been updated if necessary.

@Daverlo Daverlo force-pushed the daverlo/python branch 2 times, most recently from 7b84fad to 53f29ed Compare September 10, 2020 11:27
@Daverlo Daverlo marked this pull request as ready for review September 23, 2020 16:38
Copy link
Contributor

@marcogario marcogario left a comment

Choose a reason for hiding this comment

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

This looks good! I think you should probably get a 👍 from @RasmusWL as well.

I left a few minor comments. I think my main concern is that there are quite a few situations that we want to support (poetry, pip, etc.), and it seems worthwhile to add a test scenario for each of them, and make sure we are indeed handling them correctly.

@@ -0,0 +1,141 @@
#!/usr/bin/env python3
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you add a docstring describing what this script is for and any extra assumptions.

python-setup/auto_install_packages.py Outdated Show resolved Hide resolved
python-setup/auto_install_packages.py Show resolved Hide resolved

if python_executable_path is not None:
print("Setting CODEQL_PYTHON={}".format(python_executable_path))
print("::set-env name=CODEQL_PYTHON::{}".format(python_executable_path))
Copy link
Contributor

Choose a reason for hiding this comment

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

So the main purpose of this script is to do the installation and then set the env variable?

Is it an error if we do not suceed? do we want a different exit code?



def install_packages() -> str:
if os.path.exists('poetry.lock'):
Copy link
Contributor

Choose a reason for hiding this comment

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

You are expecting this to run in the checkout folder of the project, right?

Copy link
Member

Choose a reason for hiding this comment

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

yes!

python-setup/extractor_version.py Outdated Show resolved Hide resolved
Comment on lines +62 to +63
elif version == 3:
_check_call(['python3', '-m', 'virtualenv', venv_path])
Copy link
Contributor

Choose a reason for hiding this comment

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

Can get_extractor_version return anything else apart from 2 or 3? If it can, then we do not install the virtual env, right? Is this expected? If it cannot then I would change this into:

Suggested change
elif version == 3:
_check_call(['python3', '-m', 'virtualenv', venv_path])
else:
assert version == 3
_check_call(['python3', '-m', 'virtualenv', venv_path])

Copy link
Member

Choose a reason for hiding this comment

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

it will only return 2 or 3.

# subsequent actions in the current job, and not the current action.
export PATH="$HOME/.local/bin:$PATH"

python2 -m pip install --user --upgrade pip setuptools wheel
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it worth checking that you actually have a python2 executable?

Copy link
Member

Choose a reason for hiding this comment

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

For a long term solution it probably would be worth checking if python2 is not available and install it otherwise. For now I am not too worried -- as long as we have some automated tests that run regularly, that should catch this case right? (what do you think @Daverlo)

python-setup/install_tools.sh Outdated Show resolved Hide resolved
python3 -m pip install --user virtualenv

# venv is required for installation of poetry or pipenv (I forgot which)
sudo apt-get install -y python3-venv
Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, I dig up https://github.com/github/codeql-python-team/issues/103#issuecomment-692053819 and it seems we are expecting only the linux cloud runners to use this for now.

I haven't check yet but it would be good to have a comment saying where this should (and should not) work in the init, as that is where you can enable/disable this.

Copy link
Member

@RasmusWL RasmusWL left a comment

Choose a reason for hiding this comment

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

Thanks for the review @marcogario 👍

The context for the Python scripts (that I wrote) is that it's something I made fairly quickly, and having in mind this should hopefully only be used for a limited time, I didn't invest a lot of effort into making this the highest quality code. I'll fix up some of the most blatant errors and bad coding practices.

Comment on lines +46 to +47
else:
return buildtools.discover.get_version()
Copy link
Member

Choose a reason for hiding this comment

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

I think pylint has a standard rule making the same recommendation as you propose here, but I strongly disagree, since the control flow of the code is much easier to follow with the explicit else (in my opinion).

# subsequent actions in the current job, and not the current action.
export PATH="$HOME/.local/bin:$PATH"

python2 -m pip install --user --upgrade pip setuptools wheel
Copy link
Member

Choose a reason for hiding this comment

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

For a long term solution it probably would be worth checking if python2 is not available and install it otherwise. For now I am not too worried -- as long as we have some automated tests that run regularly, that should catch this case right? (what do you think @Daverlo)

Comment on lines +62 to +63
elif version == 3:
_check_call(['python3', '-m', 'virtualenv', venv_path])
Copy link
Member

Choose a reason for hiding this comment

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

it will only return 2 or 3.



def install_packages() -> str:
if os.path.exists('poetry.lock'):
Copy link
Member

Choose a reason for hiding this comment

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

yes!

print('Found Pipfile, will install packages with Pipenv', flush=True)
return install_packages_with_pipenv()

version = extractor_version.get_extractor_version(sys.argv[1], quiet=False)
Copy link
Member

Choose a reason for hiding this comment

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

We should be passing in codeql_base_dir for sure 👍

We could run get_extractor_version before calling install_packages, I just didn't... if you feel very strongly about this one, let me know.

print('Found Pipfile, will install packages with Pipenv', flush=True)
return install_packages_with_pipenv()

version = extractor_version.get_extractor_version(sys.argv[1], quiet=False)
Copy link
Member

Choose a reason for hiding this comment

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

ehh, naming is apparently not too obvious. extractor_version.get_extractor_version returns the Python version the extractor thinks this repo is in.

python-setup/auto_install_packages.py Outdated Show resolved Hide resolved
python-setup/auto_install_packages.py Show resolved Hide resolved
@RasmusWL
Copy link
Member

@Daverlo I comitted directly to the branch with my changes. That means I actually haven't run the script, which is kind of scary. Is it easy to add tests so we know the script is working? (or have they already been added?)

@Daverlo
Copy link
Contributor Author

Daverlo commented Sep 25, 2020

Tests are not going to be too helpful, if it doesn't work we just show a warning, and those are not easily visible. In this action this process failed on purpose https://github.com/dsp-testing/daverlo-djanjo-test/actions/runs/272089425, but you see all green no warning in the actions page https://github.com/dsp-testing/daverlo-djanjo-test/actions and in the pr page https://github.com/dsp-testing/daverlo-djanjo-test/pull/2

I would propose that we run the different tests on the django-test repo (basically update the workflows that I created for https://github.com/github/codeql-python-team/issues/103#issuecomment-663252898 so they run every day).

Do you have any suggestion on how can we do better testing?

@marcogario
Copy link
Contributor

Do you have any suggestion on how can we do better testing?

I think the typescript wrapper is not too complex. I would expect we can test the python script directly. Ideally these should all complete outputting the env for CODEQL and you can check that. Maybe create a new workflow file for this.

@Daverlo
Copy link
Contributor Author

Daverlo commented Sep 29, 2020

I've added a modified version of the playground workflow for testing the scripts. https://github.com/github/codeql-action/actions/runs/278176450

@RasmusWL That should cover all the cases am I right?

@RasmusWL
Copy link
Member

I've added a modified version of the playground workflow for testing the scripts. https://github.com/github/codeql-action/actions/runs/278176450

@RasmusWL That should cover all the cases am I right?

Nice 👍

Unfortunate about the "expected failures", but not something I will personally worry too much about.

This should allow us to catch blatant error in the python script early, which is super good 🎉

I would propose that we run the different tests on the django-test repo (basically update the workflows that I created for github/codeql-python-team#103 (comment) so they run every day).

Is this still our best approach for something similar for integration tests?

@Daverlo
Copy link
Contributor Author

Daverlo commented Sep 29, 2020

Is this still our best approach for something similar for integration tests?

Yep, but as @marcogario suggested, by testing the scripts we should be quite covered

I think the typescript wrapper is not too complex. I would expect we can test the python script directly. Ideally these should all complete outputting the env for CODEQL and you can check that. Maybe create a new workflow file for this.

Copy link
Contributor

@marcogario marcogario left a comment

Choose a reason for hiding this comment

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

With the testing in place, this is good on my side.

We might want to keep the cases in which we know we will fail in the tests, but that is a minor.

$GITHUB_WORKSPACE/python-setup/install_tools.sh
echo -e '\n\n\n\n\n' && sleep 0.5
cd $GITHUB_WORKSPACE/${{ matrix.test_dir }}
$GITHUB_WORKSPACE/python-setup/auto_install_packages.py /opt/hostedtoolcache/CodeQL/0.0.0-20200826/x64/codeql/
Copy link
Contributor

Choose a reason for hiding this comment

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

This will break when we upgrade the bundle version. Can you do a find before to get the version of the bunde against /opt/hostedtoolcache/CodeQL/0.0.0-XXXX/x64/codeql ?

Copy link
Member

Choose a reason for hiding this comment

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

This used to be set as an environment variable, but last time I had to run my scripts it was removed 😞 so that one is probably on me, although I have no idea of how to properly fix it.

Copy link
Contributor

Choose a reason for hiding this comment

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

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.

3 participants