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

Publish to PyPi as a Trusted Publisher #187

Merged
merged 5 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 0 additions & 7 deletions .github/workflows/README.md

This file was deleted.

6 changes: 5 additions & 1 deletion .github/workflows/check-release-notes.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
# This workflow checks whether the user remembered to update
# the changelog with a relevant entry for the PR.
# This check is skipped if the PR has the "skip news" label.
name: Check Release Notes

on:
pull_request:
types: [ opened, synchronize, reopened, labeled, unlabeled ]

jobs:
build:
check:
name: Check for entry in Changelog
runs-on: ubuntu-latest
timeout-minutes: 1
steps:
- uses: actions/checkout@v4
- name: Grep Changelog for PR number
Expand Down
12 changes: 11 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
name: CI
# Run all CI checks on all pushes to the main branch or pull-request updates.
# This includes running static checks such as linting and type checking,
# as well as running the test suite on all supported Python versions.
# Coverage reports will be uploaded to Codecov and Codacy.
#
# The documentation will also be built, and a link to the docs will be
# added to the PR description.
name: CI checks

on:
push:
Expand All @@ -15,6 +22,7 @@ jobs:
documentation-links:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
timeout-minutes: 1
steps:
- uses: readthedocs/actions/preview@v1
with:
Expand All @@ -24,6 +32,7 @@ jobs:
static-checks:
name: Static checks
runs-on: ubuntu-latest
timeout-minutes: 6
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-python
Expand Down Expand Up @@ -63,6 +72,7 @@ jobs:
# - windows-latest
fail-fast: true
runs-on: ${{ matrix.os }}
timeout-minutes: 8
steps:
- uses: actions/checkout@v4

Expand Down
122 changes: 101 additions & 21 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -1,40 +1,120 @@
name: Release workflow
# This workflow builds source (sdist) and binary (wheel) distributions
# for the Python package on every push event, followed by publishing
# them to TestPyPi. This should be a good indicator that the build
# and publishing process is always working correctly (as opposed
# to only finding out when we actually want to publish a new
# release).
#
# When new tags are pushed - in addition to the steps above -
# we also publish the build distributions to the "real" PyPi
# repository, and publish a new GitHub Release containing
# the latest section extracted from the release notes
# and the Sigstore-certified built distributions.
name: Release workflow 🚀

on:
push:
tags:
- "*.*.*"
on: push

jobs:
release:
build:
name: Build distributions
runs-on: ubuntu-latest
timeout-minutes: 6
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-python
with:
python-version: "3.8"
requirements: tox
- name: Generate release notes
run: tox -e release-notes
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
- name: Build source (sdist) and binary (wheel) distributions
run: tox -e build-dists
- uses: actions/upload-artifact@v3
with:
body_path: LATEST_RELEASE_NOTES.md
name: python-package-distributions
path: dist/

publish-to-testpypi:
name: Publish distribution to TestPyPI
needs:
- build
runs-on: ubuntu-latest
timeout-minutes: 2
environment:
name: testpypi
url: https://test.pypi.org/p/ridgeplot
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
steps:
- uses: actions/download-artifact@v3
with:
name: python-package-distributions
path: dist/
- uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
skip-existing: true
verbose: true
print-hash: true

publish-to-pypi:
name: Publish distribution to PyPI
if: startsWith(github.ref, 'refs/tags/')
needs:
- build
- publish-to-testpypi
runs-on: ubuntu-latest
timeout-minutes: 2
environment:
name: pypi
url: https://pypi.org/p/ridgeplot
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
steps:
- uses: actions/download-artifact@v3
with:
name: python-package-distributions
path: dist/
- uses: pypa/gh-action-pypi-publish@release/v1
with:
verbose: true
print-hash: true

build-and-publish-to-pypi:
needs: release
github-release:
name: Publish a GitHub Release
needs:
- publish-to-pypi
runs-on: ubuntu-latest
timeout-minutes: 2
permissions:
contents: write # IMPORTANT: mandatory for making GitHub Releases
id-token: write # IMPORTANT: mandatory for sigstore
steps:

# Generate the release notes
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-python
with:
python-version: "3.8"
requirements: tox
- name: Build and publish a release to TestPyPI
env:
TWINE_PASSWORD: "${{ secrets.PYPI_TOKEN_TEST }}"
run: tox -e publish-pypi-test
- name: Build and publish a release PyPI
env:
TWINE_PASSWORD: "${{ secrets.PYPI_TOKEN }}"
run: tox -e publish-pypi-prod
- name: Generate release notes
run: tox -e release-notes

# Sign the package distributions with Sigstore
# https://github.com/marketplace/actions/gh-action-sigstore-python
- uses: actions/download-artifact@v3
with:
name: python-package-distributions
path: dist/
- name: Sign the dists with Sigstore
uses: sigstore/gh-action-sigstore-python@v1.2.3
with:
inputs: >-
./dist/*.tar.gz
./dist/*.whl

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
body_path: LATEST_RELEASE_NOTES.md
# `dist/` contains the built distributions, and the
# Sigstore-produced signatures and certificates.
files: dist/**
14 changes: 13 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
default_language_version:
python: python3.8
python: python3.8

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
Expand Down Expand Up @@ -30,6 +30,18 @@ repos:
- id: trailing-whitespace
exclude: .bumpversion.cfg

- repo: https://github.com/python-jsonschema/check-jsonschema.git
rev: 0.28.2
hooks:
- id: check-github-actions
- id: check-github-workflows
- id: check-jsonschema
name: "Check GitHub Workflows set timeout-minutes"
files: ^\.github/workflows/[^/]+$
types: [ yaml ]
args: [ "--builtin-schema", "github-workflows-require-timeout" ]
- id: check-readthedocs

- repo: https://github.com/codespell-project/codespell
rev: v2.2.6
hooks:
Expand Down
6 changes: 6 additions & 0 deletions docs/reference/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ This document outlines the list of changes to ridgeplot between each release. Fo
Unreleased changes
------------------

- ...

### CI/CD

- Move all CI/CD utilities to the `cicd_utils/` directory ({gh-issue}`186`)
- Publish to PyPi as a Trusted Publisher ({gh-issue}`187`)
- Add `check-jsonschema` pre-commit hooks and define `timeout-minutes` for all GitHub workflows ({gh-issue}`187`)

---

Expand Down
9 changes: 2 additions & 7 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,13 @@ deps =
mdformat
commands = python cicd_utils/scripts/extract_latest_release_notes.py

[testenv:publish-pypi-{test,prod}]
description = build and upload the source and wheel package to (test/prod) PyPI
[testenv:build-dists]
description = build source (sdist) and binary (wheel) distributions
deps =
build
twine
allowlist_externals = rm
passenv =
{[testenv]passenv}
TWINE_PASSWORD
commands =
rm -rf dist/
python -m build
twine check --strict dist/*
test: twine upload --verbose --repository testpypi dist/*
prod: twine upload --verbose dist/*