diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 3e66f4fb0..d64123c60 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -25,10 +25,11 @@ permissions: jobs: build: runs-on: ubuntu-latest + outputs: + hashes: ${{ steps.hash.outputs.hashes }} steps: - uses: actions/checkout@v4 with: - token: ${{ secrets.ACTIONS_ACCESS_TOKEN }} ref: ${{ inputs.tag }} - name: Install the latest version of rye uses: eifinger/setup-rye@v2 @@ -43,10 +44,25 @@ jobs: run: | rye sync rye build + - name: "Generate hashes" + id: hash + run: | + cd dist && echo "hashes=$(sha256sum * | base64 -w0)" >> $GITHUB_OUTPUT - uses: actions/upload-artifact@v4 with: name: build path: ./dist + provenance_python: + needs: [build] + permissions: + actions: read + contents: write + id-token: write # Needed to access the workflow's OIDC identity. + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0 + with: + base64-subjects: "${{ needs.build.outputs.hashes }}" + upload-assets: true + upload-tag-name: ${{ inputs.tag }} # Tag from the initiation of the workflow test-build: if: ${{ !inputs.skip-tests }} needs: ['build'] @@ -73,7 +89,6 @@ jobs: steps: - uses: actions/checkout@v4 with: - token: ${{ secrets.ACTIONS_ACCESS_TOKEN }} ref: ${{ inputs.tag }} - name: Install the latest version of rye uses: eifinger/setup-rye@v2 @@ -115,6 +130,24 @@ jobs: rye add labelbox --path ./$(find ./dist/ -name *.tar.gz) --sync --absolute --features data cd libs/labelbox rye run pytest tests/data + publish-python-package-to-release: + runs-on: ubuntu-latest + needs: ['build'] + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.tag }} + - uses: actions/download-artifact@v4 + with: + name: build + path: ./artifact + - name: Upload dist to release + run: | + gh release upload ${{ inputs.tag }} ./artifact/* + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} pypi-publish: runs-on: ubuntu-latest needs: ['build', 'test-build'] @@ -141,6 +174,9 @@ jobs: needs: ['build', 'test-build'] permissions: packages: write + outputs: + image: ${{ steps.image.outputs.image }} + digest: ${{ steps.build_container.outputs.digest }} if: | always() && (needs.test-build.result == 'success' || needs.test-build.result == 'skipped') && github.event.inputs.tag @@ -149,7 +185,6 @@ jobs: steps: - uses: actions/checkout@v4 with: - token: ${{ secrets.ACTIONS_ACCESS_TOKEN }} ref: ${{ inputs.tag }} - name: downcase CONTAINER_IMAGE @@ -168,6 +203,7 @@ jobs: - name: Build and push uses: docker/build-push-action@v5 + id: build_container with: context: . file: ./libs/labelbox/Dockerfile @@ -181,5 +217,24 @@ jobs: tags: | ${{ env.CONTAINER_IMAGE }}:latest ${{ env.CONTAINER_IMAGE }}:${{ inputs.tag }} - -# Note that the build and pypi-publish jobs are split so that the additional permissions are only granted to the pypi-publish job. \ No newline at end of file + - name: Output image + id: image + run: | + # NOTE: Set the image as an output because the `env` context is not + # available to the inputs of a reusable workflow call. + image_name="${CONTAINER_IMAGE}" + echo "image=$image_name" >> "$GITHUB_OUTPUT" + + provenance_container: + needs: [container-publish] + permissions: + actions: read # for detecting the Github Actions environment. + id-token: write # for creating OIDC tokens for signing. + packages: write # for uploading attestations. + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0 + with: + image: ${{ needs. container-publish.outputs.image }} + digest: ${{ needs. container-publish.outputs.digest }} + registry-username: ${{ github.actor }} + secrets: + registry-password: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/python-package-develop.yml b/.github/workflows/python-package-develop.yml index cd5110033..b25c1a6dd 100644 --- a/.github/workflows/python-package-develop.yml +++ b/.github/workflows/python-package-develop.yml @@ -54,7 +54,6 @@ jobs: steps: - uses: actions/checkout@v4 with: - token: ${{ secrets.ACTIONS_ACCESS_TOKEN }} ref: ${{ github.head_ref }} - uses: ./.github/actions/python-package-shared-setup with: @@ -85,7 +84,6 @@ jobs: steps: - uses: actions/checkout@v4 with: - token: ${{ secrets.ACTIONS_ACCESS_TOKEN }} ref: ${{ github.head_ref }} - name: downcase CONTAINER_IMAGE diff --git a/.github/workflows/python-package-shared.yml b/.github/workflows/python-package-shared.yml index 16115bfdb..b6e5bbe9e 100644 --- a/.github/workflows/python-package-shared.yml +++ b/.github/workflows/python-package-shared.yml @@ -25,7 +25,6 @@ jobs: steps: - uses: actions/checkout@v4 with: - token: ${{ secrets.ACTIONS_ACCESS_TOKEN }} ref: ${{ github.head_ref }} - uses: ./.github/actions/python-package-shared-setup with: @@ -42,7 +41,6 @@ jobs: steps: - uses: actions/checkout@v4 with: - token: ${{ secrets.ACTIONS_ACCESS_TOKEN }} ref: ${{ github.head_ref }} - uses: ./.github/actions/python-package-shared-setup with: @@ -61,7 +59,6 @@ jobs: steps: - uses: actions/checkout@v4 with: - token: ${{ secrets.ACTIONS_ACCESS_TOKEN }} ref: ${{ github.head_ref }} - uses: ./.github/actions/python-package-shared-setup with: diff --git a/README.md b/README.md index 634defa73..26e659da2 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ [![Twitter Follow](https://img.shields.io/twitter/follow/labelbox.svg?style=social&label=Follow)](https://twitter.com/labelbox) [![LinkedIn Follow](https://img.shields.io/badge/Follow-LinkedIn-blue.svg?style=flat&logo=linkedin)](https://www.linkedin.com/company/labelbox/) [![Supported Python Versions](https://img.shields.io/pypi/pyversions/labelbox)](https://img.shields.io/pypi/pyversions/labelbox) +[![SLSA 3](https://slsa.dev/images/gh-badge-level3.svg)](https://slsa.dev) # Labelbox @@ -94,4 +95,23 @@ c.InteractiveShellApp.exec_lines = [ 'import sys; sys.path.insert(0, "")' ] ``` -4. Go to the root of your project and run `jupyter notebook` to start the server. \ No newline at end of file +4. Go to the root of your project and run `jupyter notebook` to start the server. + +## Provenance + +To enhance the software supply chain security of Labelbox's users, as of v.3.72.2, every Labelbox SDK release contains a [SLSA Level 3 Provenance](https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/generic/README.md) document. +This document provides detailed information about the build process, including the repository and branch from which the package was generated. + +By using the [SLSA framework's official verifier](https://github.com/slsa-framework/slsa-verifier), you can verify the provenance document to ensure that the package is from a trusted source. Verifying the provenance helps confirm that the package has not been tampered with and was built in a secure environment. + +Example of usage for the v.3.72.2 release wheel: + +``` +VERSION=v.3.72.2 #tag +pip download --no-deps labelbox==${VERSION} + +curl --location -O \ + https://github.com/Labelbox/labelbox-python/releases/download/${VERSION}/multiple.intoto.jsonl + +slsa-verifier verify-artifact --source-branch develop --builder-id 'https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@refs/tags/v2.0.0' --source-uri "git+https://github.com/Labelbox/labelbox-python" --provenance-path multiple.intoto.jsonl ./labelbox-${VERSION}-py3-none-any.whl +```