Chore: Bump version, disable legacy workflows (#53) #1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
# SPDX-License-Identifier: Apache-2.0 | |
# SPDX-FileCopyrightText: 2024 The Linux Foundation <https://linuxfoundation.org> | |
name: "🤖 DevOps Automation" | |
# yamllint disable-line rule:truthy | |
on: | |
workflow_dispatch: | |
push: | |
branches: [main, master] | |
env: | |
DEFAULT_PYTHON: "3.10" | |
BUILD_ARTEFACTS: "dist" | |
# Configures publishing to PyPI | |
PYPI_PUBLISHING: "true" | |
# Create GitHub releases for all builds, not just production builds | |
GITHUB_RELEASE_ALWAYS: "true" | |
# Create an initial tag, if missing | |
CREATE_MISSING_TAG: "true" | |
jobs: | |
classify-content: | |
name: "Inspect Repository" | |
runs-on: ubuntu-latest | |
outputs: | |
python: ${{ steps.classify.outputs.python }} | |
notebooks: ${{ steps.classify.outputs.notebooks }} | |
steps: | |
- uses: actions/checkout@v4 | |
- name: "Classify content" | |
id: classify | |
# yamllint disable-line rule:line-length | |
uses: os-climate/osc-github-devops/.github/actions/repository-classify-content@main | |
github-workflow-metadata: | |
name: "Gather Workflow Metadata" | |
runs-on: ubuntu-latest | |
outputs: | |
owner: ${{ steps.set.outputs.owner }} | |
repository: ${{ steps.set.outputs.repository }} | |
tagged: ${{ steps.set.outputs.tagged }} | |
steps: | |
- name: "Capture workflow metadata" | |
id: set | |
# yamllint disable-line rule:line-length | |
uses: os-climate/osc-github-devops/.github/actions/github-workflow-metadata@main | |
verify-repository-labels: | |
name: "Verify Repository Labels" | |
runs-on: ubuntu-latest | |
outputs: | |
present: ${{ steps.labelling.outputs.present }} | |
created: ${{ steps.labelling.outputs.created }} | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
steps: | |
- name: "Verify/create release labels" | |
id: labelling | |
# yamllint disable-line rule:line-length | |
uses: os-climate/osc-github-devops/.github/actions/github-mandatory-labels@main | |
python-project: | |
name: "Python Project" | |
needs: | |
- classify-content | |
if: needs.classify-content.outputs.python == 'true' | |
runs-on: ubuntu-latest | |
outputs: | |
matrix: ${{ steps.python.outputs.matrixjson }} | |
permissions: | |
# IMPORTANT: mandatory to raise the PR | |
id-token: write | |
pull-requests: write | |
repository-projects: write | |
contents: write | |
steps: | |
- uses: actions/checkout@v4 | |
- name: "Extract Python versioning" | |
id: python | |
# yamllint disable-line rule:line-length | |
uses: os-climate/osc-github-devops/.github/actions/python-versions-matrix@main | |
python-build: | |
name: "Python Build" | |
needs: | |
- github-workflow-metadata | |
- python-project | |
runs-on: "ubuntu-latest" | |
continue-on-error: false | |
strategy: | |
fail-fast: false | |
matrix: ${{ fromJson(needs.python-project.outputs.matrix) }} | |
permissions: | |
contents: write | |
# Required by SigStore signing action | |
id-token: write | |
outputs: | |
publish: ${{ steps.python-project-build.outputs.publish }} | |
steps: | |
- uses: actions/checkout@v4 | |
- name: "Set up Python ${{ matrix.python-version }}" | |
uses: actions/setup-python@v5 | |
with: | |
python-version: ${{ matrix.python-version }} | |
- name: "Install PDM tooling" | |
uses: pdm-project/setup-pdm@v4 | |
with: | |
python-version: ${{ matrix.python-version }} | |
- name: "Action: semantic-tag-latest" | |
id: semantic-tag-latest | |
# yamllint disable-line rule:line-length | |
uses: os-climate/osc-github-devops/.github/actions/semantic-tag-latest@main | |
- name: "Create initial v0.0.1 tag [conditional]" | |
id: set-initial-tag | |
if: steps.semantic-tag-latest.outputs.invalid == 'true' && env.CREATE_MISSING_TAG | |
uses: softprops/action-gh-release@v2 | |
with: | |
token: ${{ secrets.GITHUB_TOKEN }} | |
prerelease: true | |
tag_name: v0.0.1 | |
- name: "Build: Python project" | |
id: python-project-build | |
if: steps.semantic-tag-latest.outputs.invalid == 'false' | |
# yamllint disable-line rule:line-length | |
uses: os-climate/osc-github-devops/.github/actions/python-project-build@main | |
with: | |
artefact_output_path: "dist" | |
purge_output_path: "true" | |
- name: "Validate artefacts with Twine" | |
id: python-twine-check | |
# yamllint disable-line rule:line-length | |
uses: os-climate/osc-github-devops/.github/actions/python-twine-check@main | |
- name: "Upload build artefacts" | |
uses: actions/upload-artifact@v4 | |
if: matrix.python-version == env.DEFAULT_PYTHON | |
with: | |
name: ${{ github.ref_name }} | |
path: ${{ env.BUILD_ARTEFACTS }} | |
- name: "Sign packages with SigStore" | |
uses: sigstore/[email protected] | |
if: matrix.python-version == env.DEFAULT_PYTHON | |
env: | |
package-path: ${{ env.BUILD_ARTEFACTS }} | |
with: | |
inputs: >- | |
./${{ env.BUILD_ARTEFACTS }}/*.tar.gz | |
./${{ env.BUILD_ARTEFACTS }}/*.whl | |
github: | |
name: "Publish to GitHub" | |
# Only publish on tag pushes | |
needs: python-build | |
runs-on: ubuntu-latest | |
permissions: | |
# IMPORTANT: mandatory to publish artefacts | |
contents: write | |
# Ensure development builds are NOT uploaded when build naming is broken | |
# if: github.ref_name != 'main' | |
steps: | |
- name: "⬇ Download build artefacts" | |
uses: actions/download-artifact@v4 | |
with: | |
name: ${{ github.ref_name }} | |
path: ${{ env.BUILD_ARTEFACTS }} | |
- name: "Publish DEVELOPMENT artefacts to GitHub" | |
if: (startsWith(github.ref, 'refs/tags/') != true) && (env.GITHUB_RELEASE_ALWAYS == 'true') | |
uses: softprops/action-gh-release@v2 | |
with: | |
token: ${{ secrets.GITHUB_TOKEN }} | |
prerelease: true | |
tag_name: ${{ github.ref_name }}-dev | |
name: "Test/Development Build: ${{ github.ref_name }}" | |
# body_path: ${{ github.workspace }}/CHANGELOG.rst | |
files: | | |
${{ env.BUILD_ARTEFACTS }}/*.tar.gz | |
${{ env.BUILD_ARTEFACTS }}/*.whl | |
${{ env.BUILD_ARTEFACTS }}/*.sigstore* | |
- name: "Publish PRODUCTION artefacts to GitHub" | |
if: startsWith(github.ref, 'refs/tags/') | |
uses: softprops/action-gh-release@v2 | |
with: | |
token: ${{ secrets.GITHUB_TOKEN }} | |
prerelease: false | |
tag_name: ${{ github.ref_name }} | |
name: "Test/Development Build: ${{ github.ref_name }}" | |
# body_path: ${{ github.workspace }}/CHANGELOG.rst | |
files: | | |
${{ env.BUILD_ARTEFACTS }}/*.tar.gz | |
${{ env.BUILD_ARTEFACTS }}/*.whl | |
${{ env.BUILD_ARTEFACTS }}/*.sigstore* | |
testpypi: | |
name: "Test Package Publishing" | |
# Only publish on tag pushes | |
# if: startsWith(github.ref, 'refs/tags/') | |
needs: | |
- github-workflow-metadata | |
- python-build | |
runs-on: ubuntu-latest | |
environment: | |
name: development | |
permissions: | |
# IMPORTANT: mandatory for trusted publishing | |
id-token: write | |
steps: | |
- name: "Download build artefacts" | |
uses: actions/download-artifact@v4 | |
if: env.PYPI_PUBLISHING == 'true' | |
with: | |
name: ${{ github.ref_name }} | |
path: ${{ env.BUILD_ARTEFACTS }} | |
- name: "Manicure artefacts directory" | |
id: files | |
run: | | |
# Remove file types unsupported by the Python Package Index | |
if [ ! -d ${{ env.BUILD_ARTEFACTS }} ]; then | |
echo "Early exit; build artefacts path NOT found: ${{ env.BUILD_ARTEFACTS }}" | |
exit 0 | |
fi | |
if [ -f ${{ env.BUILD_ARTEFACTS }}/buildvars.txt ]; then | |
rm ${{ env.BUILD_ARTEFACTS }}/buildvars.txt | |
else | |
echo "No buildvars.txt file to purge" | |
fi | |
# Remove outputs related to SigStore signing | |
if test -n "$(find ${{ env.BUILD_ARTEFACTS }} -maxdepth 1 -name '**.sigstore*' -print -quit)" | |
then | |
echo "Found SigStore signing artefacts to purge" | |
rm ${{ env.BUILD_ARTEFACTS }}/*.sigstore* | |
else | |
echo "No SigStore signing artefacts to purge" | |
fi | |
- name: "Check presence in Test PyPI" | |
id: url-check | |
# yamllint disable-line rule:line-length | |
uses: os-climate/osc-github-devops/.github/actions/url-validity-check@main | |
with: | |
prefix: "https://test.pypi.org/project" | |
# Use project name, e.g. "/ITR" | |
string: "/${{ needs.github-workflow-metadata.outputs.repository }}" | |
suffix: "/" | |
- name: "Publish to Test PyPI [Trusted Publishing]" | |
uses: pypa/gh-action-pypi-publish@release/v1 | |
# Primary/default method uses trusted publishing | |
if: steps.url-check.outputs.valid == 'true' | |
with: | |
repository-url: https://test.pypi.org/legacy/ | |
# Show checksum values | |
print-hash: true | |
packages-dir: ${{ env.BUILD_ARTEFACTS }} | |
# We already validate earlier in the pipeline | |
verify-metadata: false | |
# Test releases are always debugged | |
verbose: true | |
- name: "Publish to Test PyPI [Fallback: API Key]" | |
uses: pypa/gh-action-pypi-publish@release/v1 | |
# Fallback method uses static organisation credentials | |
# Used initially when trusted publishing is unavailable | |
if: steps.url-check.outputs.valid == 'false' | |
with: | |
repository-url: https://test.pypi.org/legacy/ | |
# Show checksum values | |
print-hash: true | |
packages-dir: ${{ env.BUILD_ARTEFACTS }} | |
# We already validate earlier in the pipeline | |
verify-metadata: false | |
# Test releases are always debugged | |
verbose: true | |
# Organisation secret/variable | |
# Defined/stored in 1Password | |
password: ${{ secrets.OSC_GITHUB_PYPI_TEST_TOKEN }} | |
pypi: | |
name: "Publish Package" | |
# Only publish on tag pushes | |
needs: [python-build, github-workflow-metadata, testpypi] | |
runs-on: ubuntu-latest | |
environment: | |
name: production | |
permissions: | |
# IMPORTANT: mandatory for trusted publishing | |
id-token: write | |
steps: | |
- name: "Download build artefacts" | |
uses: actions/download-artifact@v4 | |
with: | |
name: ${{ github.ref_name }} | |
path: ${{ env.BUILD_ARTEFACTS }} | |
- name: "Remove unsupported artefacts/files" | |
run: | | |
# Remove unsupported artefacts/files | |
if (ls ${{ env.BUILD_ARTEFACTS }}/*.sigstore*); then | |
rm ${{ env.BUILD_ARTEFACTS }}/*.sigstore* | |
fi | |
- name: "Check if present in PyPI" | |
id: url-check | |
# yamllint disable-line rule:line-length | |
uses: os-climate/osc-github-devops/.github/actions/url-validity-check@main | |
with: | |
prefix: "https://pypi.org/project" | |
# Use project name, e.g. "/ITR" | |
string: "/${{ needs.github-workflow-metadata.outputs.repository }}" | |
suffix: "/" | |
- name: "Publish to PyPI [Trusted Publishing]" | |
uses: pypa/gh-action-pypi-publish@release/v1 | |
# Primary/default method uses trusted publishing | |
if: steps.url-check.outputs.valid == 'true' | |
with: | |
# Show checksum values | |
print-hash: true | |
packages-dir: ${{ env.BUILD_ARTEFACTS }} | |
# We already validate earlier in the pipeline | |
verify-metadata: false | |
- name: "Publish to PyPI [Fallback: API Key]" | |
uses: pypa/gh-action-pypi-publish@release/v1 | |
# Fallback method uses static organisation credentials | |
# Used initially when trusted publishing is unavailable | |
if: steps.url-check.outputs.valid == 'false' | |
with: | |
# Show checksum values | |
print-hash: true | |
packages-dir: ${{ env.BUILD_ARTEFACTS }} | |
# We already validate earlier in the pipeline | |
verify-metadata: false | |
# Organisation secret/variable | |
# Defined/stored in 1Password | |
password: ${{ secrets.OSC_GITHUB_PYPI_TOKEN }} | |
notebooks: | |
name: "Jupyter Notebooks" | |
needs: | |
- classify-content | |
- python-project | |
runs-on: "ubuntu-latest" | |
continue-on-error: false | |
strategy: | |
fail-fast: false | |
matrix: ${{ fromJson(needs.python-project.outputs.matrix) }} | |
# Don't run when pull request is merged, only if Jupyter Notebooks are present | |
if: needs.classify-content.outputs.notebooks == 'true' | |
steps: | |
- uses: actions/checkout@v4 | |
- name: "Setup Python" | |
uses: actions/setup-python@v5 | |
with: | |
python-version: ${{ matrix.python-version }} | |
- name: "Set up Python ${{ matrix.python-version }}" | |
uses: actions/setup-python@v5 | |
with: | |
python-version: ${{ matrix.python-version }} | |
- name: "Install PDM tooling" | |
uses: pdm-project/setup-pdm@v4 | |
with: | |
python-version: ${{ matrix.python-version }} | |
- name: "Install package dependencies" | |
run: | | |
# Install build dependencies | |
python -m pip install -q --upgrade pip | |
pdm export -o requirements.txt | |
if [ -f requirements.txt ]; then | |
pip install -r requirements.txt | |
fi | |
pip install -q . | |
pip install -q pytest nbmake | |
- name: "Testing Jupyter notebooks" | |
run: | | |
# Testing Jupyter notebooks | |
echo "Installing required dependencies" | |
pip install --upgrade -q pytest nbmake | |
# Consider enabling the line below when debugging/testing | |
# find . -name '*.ipynb' | |
echo "Running command: pytest --nbmake -- **/*.ipynb" | |
pytest --nbmake src/*/*.ipynb --cov=src/devops_reusable_workflows | |
# Might need an __init__.py file in tests folder for notebooks there to be tested? | |
# https://stackoverflow.com/questions/47287721/coverage-py-warning-no-data-was-collected-no-data-collected | |
# pytest --nbmake tests/test_*.ipynb --cov=tests | |
# TEMP DISABLED - NEED TO CHECK - WHERE ARE THESE LOGS GENERATED??? | |
# - name: "Upload Logs" | |
# if: always() | |
# uses: actions/upload-artifact@v4 | |
# with: | |
# name: debug-logs | |
# path: /tmp/*.log | |
# retention-days: 14 | |
security: | |
name: "Security Audit" | |
needs: | |
- classify-content | |
- python-project | |
if: needs.classify-content.outputs.python == 'true' | |
runs-on: "ubuntu-latest" | |
continue-on-error: true | |
strategy: | |
fail-fast: false | |
matrix: ${{ fromJson(needs.python-project.outputs.matrix) }} | |
steps: | |
- name: "Checkout repository" | |
uses: actions/checkout@v4 | |
- name: "Set up Python ${{ matrix.python-version }}" | |
uses: actions/setup-python@v5 | |
with: | |
python-version: ${{ matrix.python-version }} | |
- name: "Install PDM tooling" | |
uses: pdm-project/setup-pdm@v4 | |
with: | |
python-version: ${{ matrix.python-version }} | |
- name: "Install dependencies" | |
run: | | |
pip install -q --upgrade pip | |
pdm lock | |
pdm export -o requirements.txt | |
python -m pip install -q -r requirements.txt | |
python -m pip install -q . | |
pip install --upgrade -q setuptools | |
pdm list --graph | |
- name: "Perform package auditing" | |
uses: pypa/[email protected] |