Skip to content

Conversation

@potiuk
Copy link
Member

@potiuk potiuk commented Nov 13, 2023

Move prepare-provider-packages to be run entirely in Breeze Python

This is a follow-up after #35586 and it depends on this one. It
moves the whole functionality of preparing provider packages to
breeze, removing the need of doing it in the Breeze CI image.

Since we have Python breeze with its own environment managed via
pipx we can now make sure that all the necessary packages are
installed in this environment and run package building in the
same environment Breeze uses.

Previously we have been running all the package building inside the
CI image for two reasons:

  • we could rely on the same version of build tools (wheel/setuptools)
    being installed in the CI image
  • security of the provider package preparation that used setuptools
    pre PEP-517 way of building packages that executed setup.py code

In order to isolate execution of potentially arbitrary code
in setup.py from the HOST environment in CI - where the host
environment might have access to secrets and tokens that would allow
it to break out of the sandbox for PRs coming from forks. The setup.py
file has been prepared by breeze using JINJA templates but it was
potentially possible to manipulate provider package directory structure
and get "Python" injection into generated setup.py, so it was safer
to run it in the isolated Breeze CI environment.

This PR makes it secure to run it in the Host environment,
because instead of generating setup.cfg and setup.py we generate
pyproject.toml with all the necessary information and we are using
PEP-517 compliant way of building provider packages - no arbitrary
code executed via setup.py is possible this way on the host,
so we can safely build provider packages in the host. We are
generating declarative pyproject.toml for that rather than imperative
setup.py, so we are safe to run the build process in the host without
being afraid of executing arbitrary code.

We are using flit as build tool - this is one of the popular build
tools - created by Python Packaging team. It is simple and not
too opinionated, it supports PEP-517 as well as PEP-621, so most of
the project mnetadata in pyproject toml can be added to PEP-621
compliant "project" section of pyproject.toml.

Together with the change we improves the process of generation of the
extracted sources for the providers. Originally we copied the whole
sources of Airflow to a single directory (provider_packages) and run
sequentially provider packages building from that single directory,
however it made it impossible to parallelise such builds - all
providers had to be built sequentially.

We change the approach now - instead of copying all airflow
sources once to the single directory, we build providers in separate
subdirectories of files/provider_packages/PROVIDER_ID and we only
copy there relevant sources (i.e. only provider's subfolder from
the "airflow/providers". This is quite a bit faster (each provider
only gets built using only its own sources so just scanning the
directory is faster) but it also allows to run package preparation
in parallel because each provider is fully isolated from others.

This PR also excludes not-needed prepare_providers_package.py
and unneded provider_packages folder used to prepare providers
before as well as bash script to build the providers and some
unused bash functions.

This change requires #35586 to bemerged first - only last commit
counts.


^ Add meaningful description above
Read the Pull Request Guidelines for more information.
In case of fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
In case of a new dependency, check compliance with the ASF 3rd Party License Policy.
In case of backwards incompatible changes please leave a note in a newsfragment file, named {pr_number}.significant.rst or {issue_number}.significant.rst, in newsfragments.

This PR moves the functionality of preparing provider documentation from
a python script inside Breeze CI image to breeze Python package.

This is the first of the series of moves that will simplify the way
how provider packages are being built and prepared with the aim of
improving security of the supply chain and make it easier to debug
and modify the release process.

Historically, release process has been run inside of Breeze for
several reasons: isolation of running package preparation from
Host environment, the need to keep separate virtualenv and because
we run verification of provider packages during release process - which
requires the CI environment with all its dependencies.

So far the process looked like this:

* bash breeze parsed the arguments
* bash breeze started the docker bash script with packages as
  parameters
* the bash script in CI image looped over the packages and run python
  prepare_provider_packages.py (twice) to generate docs and
  update changelog (this is interactive process where release manager
  makes decision on bumping versions). Those python script
  performed verification on provider.yaml files
* the bash script summarized the packages and displayed status of
  preparation

However after moving to Python based breeze, we can simplify it all
and run all those steps in Python breeze internal code - no need to
go to docker and use bash scripts. We also do not have to do
verification of provider.yaml files is done already extensively in
pre-commit.

This PR moves all this logic to inside Breeze.

There is stil remainig duplicated code in the original in-container
`prepare_provider_packages.py` remaining, this duplication will be
removed by subsequent PRs where other release management commands
for provider packages will also be moved to Breeze as follow-up
of this PR.

This PR has the following changes:

* move the provider decumentation code from `dev/provider_packages` to
  `dev/breeze/` (and from in-container to in-breeze-venv execution)
* completely removed the intermediate bash script and calling
  Python scripts from it - moving the logic to Breeze entirely
* added better diagnostics of what happens when packages are classified
  with particular types of changes (added `special` style to show it)
* cleaned and clarified `prepare-provider-documentation` commmand
  line flags
* introduce explicit "non-interactive" mode that is used to
  run and test the command in CI and to test it locally
* replace str with Path were files were used in the moved code
* add unit tests covering unit-testable parts of the moved code
* refactore the moved code to use utils available in Breeze
* split the code into packages and versions (reusable utils) and
  specific code for preparing package documentation
* cached provider.yaml information retrieved from providers
* move provider documentation templates to Breeze
* better error handling - they are now regular exceptions in Python
  process rather than interpreting the exit_codes passed from python
  sub-scripts returnig the codes to Bash
* when release manager classifies package, only relevant sections
  are generated (Features/Breaking changes) based on decision and
  changes are automatically "guessed" only if release manager
  chose the section where they would fall in
@boring-cyborg boring-cyborg bot added area:dev-tools area:helm-chart Airflow Helm Chart area:UI Related to UI/UX. For Frontend Developers. area:webserver Webserver related Issues labels Nov 13, 2023
@potiuk
Copy link
Member Author

potiuk commented Nov 13, 2023

cc: @uranusjr -> this is the second step of our simplifying and moving release preparation to be fully done in breeze. This one replaces the old setuptools build mechanism for flit. We got rid of setup.py in provider and switch the build/packaging to be PEP-517 and PEP-621 compliant.

I will later follo similar changes for Airflow as part of better security in our release process.

@potiuk
Copy link
Member Author

potiuk commented Nov 13, 2023

(I will have a blog post about security aspects of it coming)

@potiuk potiuk force-pushed the move-prepare-providers-packages-to-breeze branch from a607910 to 7154f90 Compare November 13, 2023 20:03
This is a follow-up after apache#35586 and it depends on this one. It
moves the whole functionality of preparing provider packages to
breeze, removing the need of doing it in the Breeze CI image.

Since we have Python breeze with its own environment managed via
`pipx` we can now make sure that all the necessary packages are
installed in this environment and run package building in the
same environment Breeze uses.

Previously we have been running all the package building inside the
CI image for two reasons:

* we could rely on the same version of build tools (wheel/setuptools)
  being installed in the CI image
* security of the provider package preparation that used setuptools
  pre PEP-517 way of building packages that executed setup.py code

In order to isolate execution of potentially arbitrary code
in setup.py from the HOST environment in CI - where the host
environment might have access to secrets and tokens that would allow
it to break out of the sandbox for PRs coming from forks. The setup.py
file has been prepared by breeze using JINJA templates but it was
potentially possible to manipulate provider package directory structure
and get "Python" injection into generated setup.py, so it was safer
to run it in the isolated Breeze CI environment.

This PR makes it secure to run it in the Host environment,
because instead of generating setup.cfg and setup.py we generate
pyproject.toml with all the necessary information and we are using
PEP-517 compliant way of building provider packages - no arbitrary
code executed via setup.py is possible this way on the host,
so we can safely build provider packages in the host. We are
generating declarative pyproject.toml for that rather than imperative
setup.py, so we are safe to run the build process in the host without
being afraid of executing arbitrary code.

We are using flit as build tool - this is one of the popular build
tools - created by Python Packaging team. It is simple and not
too opinionated, it supports PEP-517 as well as PEP-621, so most of
the project mnetadata in pyproject toml can be added to PEP-621
compliant "project" section of pyproject.toml.

Together with the change we improves the process of generation of the
extracted sources for the providers. Originally we copied the whole
sources of Airflow to a single directory (provider_packages) and run
sequentially provider packages building from that single directory,
however it made it impossible to parallelise such builds - all
providers had to be built sequentially.

We change the approach now - instead of copying all airflow
sources once to the single directory, we build providers in separate
subdirectories of files/provider_packages/PROVIDER_ID and we only
copy there relevant sources (i.e. only provider's subfolder from
the "airflow/providers". This is quite a bit faster (each provider
only gets built using only its own sources so just scanning the
directory is faster) but it also allows to run package preparation
in parallel because each provider is fully isolated from others.

This PR also excludes not-needed `prepare_providers_package.py`
and unneded `provider_packages` folder used to prepare providers
before as well as bash script to build the providers and some
unused bash functions.
@potiuk potiuk force-pushed the move-prepare-providers-packages-to-breeze branch from 7154f90 to d75cd72 Compare November 13, 2023 20:06
@potiuk
Copy link
Member Author

potiuk commented Nov 13, 2023

Ah.. Need to close one and re-open it from Apache repo - this way build-image will use the right code.

@potiuk potiuk closed this Nov 13, 2023
@potiuk
Copy link
Member Author

potiuk commented Nov 13, 2023

Re-opened as #35617

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:dev-tools area:helm-chart Airflow Helm Chart area:UI Related to UI/UX. For Frontend Developers. area:webserver Webserver related Issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant