Skip to content

Commit

Permalink
Add new workflows and actions (#5)
Browse files Browse the repository at this point in the history
* feat: Added a reusable workflow to publish the breaking API changes to a pull request

* ci: Set up new pre-commit hooks for type checking

* ci: Set up workflow to run pre-commit on the repo

* ci: Use a cache for pre-commit to make it run faster

* refactor: Set reusable workflows to use python version files from the repos

* feat: Added a reusable workflow for publishing test results as a comment on a Pull Request

* feat: Added a reusable workflow for running tests against a package using tox

* feat: Added a reusable workflow for running tox configurations for documentation builds and tests

* feat: Added a reusable workflow for building a Python package and verifying it can be installed

* docs: Upgrade docs to use GitHub Flavored Markdown alerts to better indicate important settings for proper usage of the workflows
  • Loading branch information
nfelt14 authored Aug 16, 2024
1 parent 6290959 commit 346cb0a
Show file tree
Hide file tree
Showing 19 changed files with 850 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: x # any version
check-latest: true
python-version-file: pyproject.toml
- name: Install package to check
run: |
pip install --upgrade .
Expand Down
85 changes: 85 additions & 0 deletions .github/workflows/_reusable-package-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
name: Package Build
on:
workflow_call:
inputs:
package-name:
description: The name of the package to build and install.
required: true
type: string
python-versions-array:
description: A valid JSON array of Python versions to validate the package
can be installed with.
required: true
type: string
operating-systems-array:
description: A valid JSON array of operating system names to validate the
package can be installed on.
required: false
default: '["ubuntu", "windows", "macos"]'
type: string
concurrency:
group: ${{ github.workflow }}-${{ github.ref }} (Reusable)
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
env:
PACKAGE_NAME: ${{ inputs.package-name }}
jobs:
# Verify the package can be built
build-package:
name: Build package
runs-on: ubuntu-latest
environment: package-build
permissions:
id-token: write
attestations: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: hynek/[email protected]
id: build-pkg
with:
attest-build-provenance-github: ${{ !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' }}
# Verify the package can be installed
install-package:
name: Install package
needs: build-package
runs-on: ${{ matrix.os-name }}-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
os-name: ${{ fromJSON(inputs.operating-systems-array) }}
python-version: ${{ fromJSON(inputs.python-versions-array) }}
steps:
- name: Download built packages
uses: actions/download-artifact@v4
with:
name: Packages
path: dist
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
check-latest: true
- name: Test installing wheel
shell: bash
run: pip install dist/*.whl
- name: Uninstall wheel
run: pip uninstall --yes "${{ env.PACKAGE_NAME }}"
- name: Test installing tarball
shell: bash
run: pip install dist/*.tar.gz
- name: Uninstall tarball
run: pip uninstall --yes "${{ env.PACKAGE_NAME }}"
# Check that all jobs passed
check-build-and-install-passed:
if: ${{ !cancelled() }}
needs: [build-package, install-package]
runs-on: ubuntu-latest
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
with:
jobs: ${{ toJSON(needs) }}
54 changes: 54 additions & 0 deletions .github/workflows/_reusable-publish-api-comparison.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
name: Publish API Breaking Change Check Results
on:
workflow_call:
permissions:
checks: write
pull-requests: write
jobs:
publish-test-results:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.event == 'pull_request' && !contains(fromJSON('["skipped", "cancelled", "failed"]'), github.event.workflow_run.conclusion) }}
steps:
- name: Download and Extract Artifacts
uses: dawidd6/action-download-artifact@v6
with:
run_id: ${{ github.event.workflow_run.id }}
name: breaking_changes
path: artifacts
- name: Check for breaking changes
run: |
if grep -Pzl '\n```\n```' artifacts/breaking_changes.md; then
echo "BREAKING_CHANGES=false" >> $GITHUB_ENV
else
echo "BREAKING_CHANGES=true" >> $GITHUB_ENV
fi
- name: Fetch PR number
id: pr
uses: 8BitJonny/[email protected]
with:
sha: ${{ github.event.workflow_run.head_sha }}
- name: Publish API Breaking Changes Check Results
uses: marocchino/sticky-pull-request-comment@v2
if: ${{ env.BREAKING_CHANGES == 'true' }}
with:
header: breaking-api-changes
number: ${{ steps.pr.outputs.number }}
recreate: true
path: artifacts/breaking_changes.md
- name: Add workflow link to comment
if: ${{ env.BREAKING_CHANGES == 'true' }}
uses: marocchino/sticky-pull-request-comment@v2
with:
header: breaking-api-changes
number: ${{ steps.pr.outputs.number }}
append: true
message: |-
<p><a href="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}">Link to workflow run</a></p>
- name: Delete comment if no breaking changes are found
if: ${{ env.BREAKING_CHANGES == 'false' }}
uses: marocchino/sticky-pull-request-comment@v2
with:
header: breaking-api-changes
number: ${{ steps.pr.outputs.number }}
delete: true
49 changes: 49 additions & 0 deletions .github/workflows/_reusable-publish-test-results.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
name: Publish Test Results
on:
workflow_call:
inputs:
operating-systems-array:
description: A valid JSON array of operating system names to publish test
results for.
required: false
default: '["ubuntu", "windows", "macos"]'
type: string
permissions:
checks: write
pull-requests: write
jobs:
publish-test-results:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.event == 'pull_request' && !contains(fromJSON('["skipped", "cancelled"]'), github.event.workflow_run.conclusion) }}
strategy:
fail-fast: false
matrix:
os-name: ${{ fromJSON(inputs.operating-systems-array) }}
steps:
- name: Download and Extract Artifacts
uses: dawidd6/action-download-artifact@v6
with:
run_id: ${{ github.event.workflow_run.id }}
name: artifact_${{ matrix.os-name }}_tests
path: artifacts
- name: Fetch PR number
id: pr
uses: 8BitJonny/[email protected]
with:
sha: ${{ github.event.workflow_run.head_sha }}
- name: Publish Test Results
uses: marocchino/sticky-pull-request-comment@v2
with:
header: test-results-${{ matrix.os-name }}
number: ${{ steps.pr.outputs.number }}
recreate: true
path: artifacts/.results_tests/github_report.md
- name: Add workflow link to comment
uses: marocchino/sticky-pull-request-comment@v2
with:
header: test-results-${{ matrix.os-name }}
number: ${{ steps.pr.outputs.number }}
append: true
message: |-
<p><a href="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}">Link to workflow run</a></p>
12 changes: 6 additions & 6 deletions .github/workflows/_reusable-sbom-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@
name: Create & Scan SBOM
on:
workflow_call:
permissions:
security-events: write
contents: write
id-token: write
attestations: write
jobs:
create-and-scan-sbom:
runs-on: ubuntu-latest
permissions:
security-events: write
contents: write
id-token: write
attestations: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: x # any version
python-version-file: pyproject.toml
- name: Create lockfile
run: |
pip install poetry
Expand Down
124 changes: 124 additions & 0 deletions .github/workflows/_reusable-test-code.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
---
name: Test code
on:
workflow_call:
inputs:
repo-name:
description: The full name of the repository to use to gate Codecov uploads,
in the format `owner/repo`.
required: true
type: string
python-versions-array:
description: A valid JSON array of Python versions to test against.
required: true
type: string
operating-systems-array:
description: A valid JSON array of operating system names to run tests on.
required: false
default: '["ubuntu", "windows", "macos"]'
type: string
upload-to-codecov:
description: A boolean indicating if coverage results should be uploaded to
Codecov.
required: false
default: false
type: boolean
concurrency:
group: ${{ github.workflow }}-${{ github.ref }} (Reusable)
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
jobs:
# Basic testing & linting
test-general:
runs-on: ${{ matrix.os-name }}-latest
strategy:
fail-fast: false
matrix:
os-name: ${{ fromJSON(inputs.operating-systems-array) }}
python-version: ${{ fromJSON(inputs.python-versions-array) }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
check-latest: true
- name: Install dependencies
run: python -m pip install tox tox-gh-actions
- name: Run tox
run: tox -v
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: artifact_${{ matrix.os-name }}_${{ matrix.python-version }}_tests_and_linting
path: |
.results_*/**
.coverage*
# Quick testing with coverage (no linting)
test-fast:
runs-on: ${{ matrix.os-name }}-latest
env:
REPO_NAME: ${{ inputs.repo-name }}
pytest_report_title: Test Results (${{ matrix.os-name }})
strategy:
fail-fast: false
matrix:
os-name: ${{ fromJSON(inputs.operating-systems-array) }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version-file: pyproject.toml
- name: Install tox
run: python -m pip install tox
- name: Run tox
run: tox -ve tests
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: artifact_${{ matrix.os-name }}_tests
path: |
.results_*/**
.coverage*
- name: Upload coverage to Codecov
uses: codecov/[email protected]
if: ${{ github.repository == env.REPO_NAME && !cancelled() }}
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./.coverage_tests.xml
name: codecov-${{ matrix.os-name }}
fail_ci_if_error: true
verbose: true
# Update the workflow summary with test results
create-job-summary:
name: Test Results
if: ${{ !cancelled() }}
needs: test-fast
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
path: artifacts
- name: Generate Summary
uses: phoenix-actions/test-reporting@v15
with:
name: Test Results
only-summary: false
output-to: step-summary
path: artifacts/**/.results_tests/results.xml
reporter: java-junit
fail-on-error: false
max-annotations: 0
# Check that all jobs passed
check-tests-passed:
if: ${{ !cancelled() }}
needs: [test-general, test-fast, create-job-summary]
runs-on: ubuntu-latest
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
with:
jobs: ${{ toJSON(needs) }}
Loading

0 comments on commit 346cb0a

Please sign in to comment.