.. _ci: ====================== Continuous Integration ====================== Continuous Integration (CI) is the method by which software is tested and built before deployment to users. A set of 'jobs' are defined in a ``.yml`` file, roughly taking the flow build - test - deploy. Each run is built from a clean environment. Workflows can be set to begin on triggers for example, a ``git push`` or a new tag. There are an array solutions for running CI, Open Astronomy recommends `GitHub Actions `__ for projects using GitHub. GitHub Actions workflows are defined in the ``.github/workflows/`` folder at the root of the repo. Open Astronomy maintains a `set of tools `__ to make configuring GitHub Actions easier. Examples ++++++++ Testing ------- In order GitHub Actions to run your workflow, it requires; an event to trigger the workflow, one or more jobs to complete and all steps must either run a script or trigger an action. Looking at this in context: .. code-block:: yaml name: Run template tests on: push: pull_request: workflow_dispatch: jobs: test: uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@v1 with: envs: | - linux: py311-test In this case the workflow is triggered on a push to a branch, a PR, or a manual trigger of the workflow (`workflow_dispatch`). The second line of the job defines the name of the job, in this case ``test``, and uses Open Astronomy's pre-defined workflow to run the tests with tox. The ``envs`` list, defines which tox environments will be run for that job. Publishing to PyPI ------------------ No Compiled Extensions ###################### Python packages should be published on `PyPI `__, which can be automated on CI. This can improve security (as fewer people need access to publish on PyPI) and make it less effort for maintainers to publish a release. When we are building and publishing releases to PyPI we only want this to happen on a `git tag `__, as opposed to on every commit. However, if we only run the build job on tags, we never have a way to test that the job works before we tag a release of our package. The OpenAstronomy publish workflows will (by default) only publish to PyPI on a tag which starts with `v` (`see here `__). Therefore, we recommend running the workflow on both push to your default branch (`main`), on tags and on manual runs. .. code-block:: yaml on: push: branches: - 'main' tag: workflow_dispatch: jobs: publish: uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish_pure_python.yml@v1 with: test_extras: test test_command: pytest --pyargs secrets: pypi_token: ${{ secrets.pypi_token }} Replace references to `` with the package to be published. To publish to PyPI we need a PyPI token, associated with your PyPI account. `Instructions on creating up your key here `__. The secret can be stored at `organisation `__ or `repo level `__ in GitHub settings. With Compiled Extensions ######################## Almost all packages on pypi also have environment specific binaries with all dependencies packaged. It is expected that a package publishes both a pure python distribution and the binary, see `here for examples `__. In this case, in addition to the running the tests, the ``with`` block also includes targets. 'Targets' are the distributions which the binary will be built for, so in this case it would be linux and MacOS 64 bit. The ``publish`` method from the Open Astronomy GitHub actions packages the module with the dependencies for the specific targets listed .. code-block:: yaml jobs: publish: uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish.yml@v1 with: test_extras: test test_command: pytest --pyargs test_package targets: | - linux - cp3?-macosx_x86_64 secrets: pypi_token: ${{ secrets.pypi_token }} .. sam, work your way to the full example use the sunkit example .. https://github.com/sunpy/sunkit-instruments/blob/main/.github/workflows/ci.yml Putting it all together ####################### Combining the above steps reveals a total workflow, build, testing and publishing .. code-block:: yaml name: package_deployment on: push: tag: jobs: test: uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@v1 with: envs: | - linux: py311 publish_python: uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish_pure_python.yml@v1 with: test_extras: test test_command: pytest --pyargs test_package secrets: pypi_token: ${{ secrets.pypi_token }} publish_binaries: publish: uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish.yml@v1 with: test_extras: test test_command: pytest --pyargs test_package targets: | - linux - cp3?-macosx_x86_64 secrets: pypi_token: ${{ secrets.pypi_token }} The ``.github/workflows/`` directory may contain several workflows such as the above. Each file may contain different workflows, with different triggers dependent on requirements.