-
Notifications
You must be signed in to change notification settings - Fork 11
142 lines (130 loc) · 6.53 KB
/
_build.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# This is a trusted builder implemented as a reusable workflow that can be called by other
# Actions workflows. It checks, tests, and builds the artifacts including SBOM and documentations,
# and computes hash digests as output to be used by a SLSA provenance generator. The artifacts are
# always uploaded for every job to be used for debugging purposes, but they will be removed within
# the specified retention days.
#
# Even though we run the build in a matrix to check against different platforms, due to a known
# limitation of reusable workflows that do not support setting strategy property from the caller
# workflow, we only generate artifacts for ubuntu-latest and Python 3.13, which can be used to
# create a release. For details see:
#
# https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations
#
# Note: if the build workflow needs to access secrets, they need to be passed by the caller using
# `secrets: inherit`. See also
#
# https://docs.github.com/en/actions/using-workflows/reusing-workflows
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions
#
# for the security recommendations.
name: Build the package
on:
workflow_call:
inputs:
disable-pip-audit:
type: boolean
required: true
description: Enable or disable running pip_audit to check installed packages for vulnerabilities
outputs:
artifacts-sha256:
value: ${{ jobs.build.outputs.artifacts-sha256 }}
description: The hash of the artifacts
permissions:
contents: read
env:
ARTIFACT_OS: ubuntu-latest # The default OS for release.
ARTIFACT_PYTHON: '3.13' # The default Python version for release.
jobs:
build:
# Uncomment the following to disable checks and tests for Draft pull requests.
# if: github.event.pull_request.draft == false
outputs:
artifacts-sha256: ${{ steps.compute-hash.outputs.artifacts-sha256 }}
name: Build Python ${{ matrix.python }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
# It is recommended to pin a Runner version specifically:
# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners
os: [ubuntu-latest, macos-latest, windows-latest]
python: ['3.10', '3.11', '3.12', '3.13']
steps:
- name: Harden Runner
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
disable-sudo: true
- name: Check out repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with:
python-version: ${{ matrix.python }}
# Using the Makefile assumes an activated virtual environment, which doesn't exist
# when running in an Action environment (https://github.com/actions/setup-python/issues/359).
# Instead we create an empty .venv folder so that the Makefile continues to function
# while Python operates within the runner's global environment. It is safe to ignore
# warnings from the Makefile about the missing virtual environment.
- name: Create empty virtual environment for Actions
run: mkdir .venv
- name: Install dependencies
run: make setup
# Audit all currently installed packages for security vulnerabilities. This step can
# be disabled by setting the repository variable DISABLE_PIP_AUDIT to 'true'.
- name: Audit installed packages
if: ${{ !inputs.disable-pip-audit }}
run: make audit
# Build the sdist and wheel distribution of the package and docs as a zip file.
# We don't need to check and test the package separately because `make dist` runs
# those targets first and only builds the package if they succeed. The Hypothesis
# profile picks the Hypothesis settings (see tests/conftest.py) which, for Github,
# disable randomized testing to avoid breaking CI.
- name: Build the package
run: make dist
env:
HYPOTHESIS_PROFILE: github
# Generate the requirements.txt that contains the hash digests of the dependencies and
# generate the SBOM using CyclonDX SBOM generator.
- name: Generate requirements.txt and SBOM
if: matrix.os == env.ARTIFACT_OS && matrix.python == env.ARTIFACT_PYTHON
run: make requirements sbom
# Remove the old requirements.txt file (which includes _all_ packages) and generate a
# new one for the package and its actual and required dependencies only.
- name: Prune packages and generate required requirements.txt
if: matrix.os == env.ARTIFACT_OS && matrix.python == env.ARTIFACT_PYTHON
run: |
rm requirements.txt
make prune requirements
# Find the paths to the artifact files that will be included in the release, compute
# the SHA digest for all the release files and encode them using Base64, and export it
# from this job.
- name: Compute package hash
if: matrix.os == env.ARTIFACT_OS && matrix.python == env.ARTIFACT_PYTHON
id: compute-hash
shell: bash
run: |
set -euo pipefail
TARBALL_PATH=$(find dist/ -type f -name "*.tar.gz")
WHEEL_PATH=$(find dist/ -type f -name "*.whl")
REQUIREMENTS_PATH=$(find dist/ -type f -name "*-requirements.txt")
SBOM_PATH=$(find dist/ -type f -name "*-sbom.json")
HTML_DOCS_PATH=$(find dist/ -type f -name "*-docs-html.zip")
MARKDOWN_DOCS_PATH=$(find dist/ -type f -name "*-docs-md.zip")
BUILD_EPOCH_PATH=$(find dist/ -type f -name "*-build-epoch.txt")
DIGEST=$(sha256sum "$TARBALL_PATH" "$WHEEL_PATH" "$REQUIREMENTS_PATH" "$SBOM_PATH" "$HTML_DOCS_PATH" "$MARKDOWN_DOCS_PATH" "$BUILD_EPOCH_PATH" | base64 -w0)
echo "Digest of artifacts is $DIGEST."
echo "artifacts-sha256=$DIGEST" >> "$GITHUB_OUTPUT"
# For now only generate artifacts for the specified OS and Python version in env variables.
# Currently reusable workflows do not support setting strategy property from the caller workflow.
- name: Upload the package artifact for debugging and release
if: matrix.os == env.ARTIFACT_OS && matrix.python == env.ARTIFACT_PYTHON
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
with:
name: artifact-${{ matrix.os }}-python-${{ matrix.python }}
path: dist
if-no-files-found: error
retention-days: 7