|
| 1 | +# Copyright (c) 2022 - 2022, Oracle and/or its affiliates. All rights reserved. |
| 2 | +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. |
| 3 | + |
| 4 | +# This is a trusted builder implemented as a reusable workflow that can be called by other |
| 5 | +# Actions workflows. It checks, tests, and builds the artifacts including SBOM and documentations, |
| 6 | +# and computes hash digests as output to be used by a SLSA provenance generator. The artifacts are |
| 7 | +# always uploaded for every job to be used for debugging purposes, but they will be removed within |
| 8 | +# the specified retention days. |
| 9 | +# |
| 10 | +# Even though we run the build in a matrix to check against different platforms, due to a known |
| 11 | +# limitation of reusable workflows that do not support setting strategy property from the caller |
| 12 | +# workflow, we only generate artifacts for ubuntu-latest and Python 3.11, which can be used to |
| 13 | +# create a release. For details see: |
| 14 | +# |
| 15 | +# https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations |
| 16 | +# |
| 17 | +# Note: if the build workflow needs to access secrets, they need to be passed by the caller using |
| 18 | +# `secrets: inherit`. See also |
| 19 | +# |
| 20 | +# https://docs.github.com/en/actions/using-workflows/reusing-workflows |
| 21 | +# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions |
| 22 | +# |
| 23 | +# for the security recommendations. |
| 24 | + |
| 25 | +name: Build the package |
| 26 | +on: |
| 27 | + workflow_call: |
| 28 | + outputs: |
| 29 | + artifacts-sha256: |
| 30 | + description: The hash of the artifacts |
| 31 | + value: ${{ jobs.build.outputs.artifacts-sha256 }} |
| 32 | +permissions: |
| 33 | + contents: read |
| 34 | +env: |
| 35 | + ARTIFACT_OS: ubuntu-latest # The default OS for release. |
| 36 | + ARTIFACT_PYTHON: '3.11' # The default Python version for release. |
| 37 | + |
| 38 | +jobs: |
| 39 | + build: |
| 40 | + outputs: |
| 41 | + artifacts-sha256: ${{ steps.compute-hash.outputs.artifacts-sha256 }} |
| 42 | + name: Build Python ${{ matrix.python }} on ${{ matrix.os }} |
| 43 | + runs-on: ${{ matrix.os }} |
| 44 | + strategy: |
| 45 | + fail-fast: false |
| 46 | + matrix: |
| 47 | + # It is recommended to pin a Runner version specifically: |
| 48 | + # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners |
| 49 | + os: [ubuntu-latest] |
| 50 | + python: ['3.11'] |
| 51 | + steps: |
| 52 | + |
| 53 | + - name: Check out repository |
| 54 | + uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0 |
| 55 | + with: |
| 56 | + fetch-depth: 0 |
| 57 | + |
| 58 | + - name: Set up Python |
| 59 | + uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 # v4.3.0 |
| 60 | + with: |
| 61 | + python-version: ${{ matrix.python }} |
| 62 | + |
| 63 | + # Using the Makefile assumes an activated virtual environment, which doesn't exist |
| 64 | + # when running in an Action environment (https://github.com/actions/setup-python/issues/359). |
| 65 | + # Instead we create an empty .venv folder so that the Makefile continues to function |
| 66 | + # while Python operates within the runner's global environment. It is safe to ignore |
| 67 | + # warnings from the Makefile about the missing virtual environment. |
| 68 | + - name: Create empty virtual environment for Actions |
| 69 | + run: mkdir .venv |
| 70 | + - name: Install dependencies |
| 71 | + run: make setup |
| 72 | + |
| 73 | + # Audit all currently installed packages for security vulnerabilities. |
| 74 | + - name: Audit installed packages |
| 75 | + run: make audit |
| 76 | + |
| 77 | + # Build the sdist and wheel distribution of the package and docs as a zip file. |
| 78 | + # We don't need to check and test the package separately because `make dist` runs |
| 79 | + # those targets first and only builds the package if they succeed. |
| 80 | + - name: Build the package |
| 81 | + run: make dist |
| 82 | + env: |
| 83 | + GITHUB_TOKEN: ${{ github.token }} |
| 84 | + |
| 85 | + # Generate the requirements.txt that contains the hash digests of the dependencies and |
| 86 | + # generate the SBOM using CyclonDX SBOM generator. |
| 87 | + - name: Generate requirements.txt and SBOM |
| 88 | + if: matrix.os == env.ARTIFACT_OS && matrix.python == env.ARTIFACT_PYTHON |
| 89 | + run: make requirements sbom |
| 90 | + |
| 91 | + # Remove the old requirements.txt file (which includes _all_ packages) and generate a |
| 92 | + # new one for the package and its actual and required dependencies only. |
| 93 | + - name: Prune packages and generate required requirements.txt |
| 94 | + if: matrix.os == env.ARTIFACT_OS && matrix.python == env.ARTIFACT_PYTHON |
| 95 | + run: | |
| 96 | + rm requirements.txt |
| 97 | + make prune requirements |
| 98 | +
|
| 99 | + # Find the paths to the artifact files that will be included in the release, compute |
| 100 | + # the SHA digest for all the release files and encode them using Base64, and export it |
| 101 | + # from this job. |
| 102 | + - name: Compute package hash |
| 103 | + if: matrix.os == env.ARTIFACT_OS && matrix.python == env.ARTIFACT_PYTHON |
| 104 | + id: compute-hash |
| 105 | + shell: bash |
| 106 | + run: | |
| 107 | + set -euo pipefail |
| 108 | + TARBALL_PATH=$(find dist/ -type f -name "*.tar.gz") |
| 109 | + WHEEL_PATH=$(find dist/ -type f -name "*.whl") |
| 110 | + GO_ACTION_PARSER=$(find bin/ -type f -name "actionparser") |
| 111 | + GO_BASH_PARSER=$(find bin/ -type f -name "bashparser") |
| 112 | + REQUIREMENTS_PATH=$(find dist/ -type f -name "*-requirements.txt") |
| 113 | + SBOM_PATH=$(find dist/ -type f -name "*-sbom.json") |
| 114 | + SBOM_GO_PATH=$(find dist/ -type f -name "*-sbom-go.json") |
| 115 | + HTML_DOCS_PATH=$(find dist/ -type f -name "*-docs-html.zip") |
| 116 | + BUILD_EPOCH_PATH=$(find dist/ -type f -name "*-build-epoch.txt") |
| 117 | + DIGEST=$(sha256sum "$TARBALL_PATH" "$WHEEL_PATH" "$REQUIREMENTS_PATH" "$SBOM_PATH" \ |
| 118 | + "$SBOM_GO_PATH" "$GO_ACTION_PARSER" "$GO_BASH_PARSER" "$HTML_DOCS_PATH" "$BUILD_EPOCH_PATH" | base64 -w0) |
| 119 | + echo "Digest of artifacts is $DIGEST." |
| 120 | + echo "artifacts-sha256=$DIGEST" >> "$GITHUB_OUTPUT" |
| 121 | +
|
| 122 | + # For now only generate artifacts for the specified OS and Python version in env variables. |
| 123 | + # Currently reusable workflows do not support setting strategy property from the caller workflow. |
| 124 | + - name: Upload the package artifact for debugging and release |
| 125 | + if: matrix.os == env.ARTIFACT_OS && matrix.python == env.ARTIFACT_PYTHON |
| 126 | + uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # v3.1.1 |
| 127 | + with: |
| 128 | + name: artifact-${{ matrix.os }}-python-${{ matrix.python }} |
| 129 | + path: | |
| 130 | + dist |
| 131 | + bin/actionparser |
| 132 | + bin/bashparser |
| 133 | + if-no-files-found: error |
| 134 | + retention-days: 7 |
0 commit comments