Skip to content

Modify how we generate sbom files #108

Modify how we generate sbom files

Modify how we generate sbom files #108

Workflow file for this run

name: Package python parsec
on:
workflow_call:
inputs:
version:
description: The version to use
type: string
required: true
workflow_dispatch:
inputs:
version:
description: The version to use (if not provided will generated one from the codespace version)
type: string
required: false
pull_request:
paths:
- .github/workflows/package-python.yml
- packaging/**
- build.py
- pyproject.toml
# We set `concurrency` to prevent having this workflow being run on code that is not up-to-date on a PR (a user make multiple push in a quick manner).
# But on the main branch, we don't want that behavior.
# Having the workflow run on each merge commit is something we would like, that could help us where a regression was made and missed by previous checks.
#
# For that we use `head_ref` that is only defined on `pull-request` and fallback to `run_id` (this is a counter, so it's value is unique between workflow call).
concurrency:
group: package-python-${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
env:
node-version: 18.12.0
python-version: 3.9
poetry-version: 1.3.2
# Cargo will be faster with this configuration.
# It will only update it's index for the dependencies that we use.
# https://blog.rust-lang.org/2023/03/09/Rust-1.68.0.html#cargos-sparse-protocol
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
permissions:
contents: read
jobs:
package-wheel:
strategy:
fail-fast: false
matrix:
include:
- name: 🐧 Linux
platform: linux
os: ubuntu-22.04
- name: 🍎 macOS
platform: macos
os: macos-12
- name: 🏁 Windows
platform: windows
os: windows-2022
name: "${{ matrix.name }}: 📦 Packaging (build Wheel)"
runs-on: ${{ matrix.os }}
outputs:
wheel-version: ${{ steps.version.outputs.full }}
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # pin v3.5.2
timeout-minutes: 5
- uses: ./.github/actions/setup-python-poetry
with:
python-version: ${{ env.python-version }}
poetry-version: ${{ env.poetry-version }}
timeout-minutes: 10
- name: Get wheel version
id: version
shell: bash
run: |
set -eux
function parse_version {
PYTHONPATH=. python3 misc/releaser.py version "$@"
}
if [ -n "${{ inputs.version }}" ]; then
parse_version "${{ inputs.version }}" | tee -a $GITHUB_OUTPUT
else
case "${{ github.event_name }}" in
workflow_call)
echo "The top workflow should have provided the version to use"
exit 2
;;
workflow_dispatch)
# No version provided, fallback to the version in the repository
parse_version --uniq-dev | tee -a $GITHUB_OUTPUT
;;
pull_request)
parse_version --uniq-dev | tee -a $GITHUB_OUTPUT
;;
*)
echo 'Unsupported event type ${{ github.event_name }}' >&2
exit 1
;;
esac
fi
- name: Set parsec version ${{ steps.version.outputs.full }}
run: python3 misc/version_updater.py --tool parsec --version ${{ steps.version.outputs.full }}
- name: Build wheel
uses: pypa/cibuildwheel@51f5c7fe68ff24694d5a6ac0eb3ad476ddd062a8 # pin v2.13.0
with:
output-dir: dist
timeout-minutes: 50
- name: Set file for wheel version
run: echo v${{ steps.version.outputs.full }} > dist/version
- name: Hack the wheel macos version
if: startsWith(matrix.os, 'macos-')
shell: bash
run: |
set -eux
# Old wheel name
OLD_WHEEL_NAME=$(basename dist/parsec_cloud-*.whl)
# Unzip the wheel
mkdir temp
cd temp
unzip ../dist/$OLD_WHEEL_NAME
# Get platform new wheel name
python -m pip install wheel
PLATFORM=$(python -c "from wheel.bdist_wheel import get_platform; print(get_platform('.'))")
NEW_WHEEL_NAME=$(basename ../dist/parsec_cloud-*.whl | sed "s/macosx_.*_x86_64/$PLATFORM/")
# Update archive and zip back
sed -i "" "s/macosx_.*_x86_64/$PLATFORM/" parsec_cloud-*.dist-info/WHEEL
zip -r $NEW_WHEEL_NAME *
cd ..
# Replace old wheel with the new one
mv temp/$NEW_WHEEL_NAME dist/
rm dist/$OLD_WHEEL_NAME
rm -rf temp
- name: Generate requirements & constraints infos
run: python packaging/wheel/wheel_it.py . --output dist --skip-wheel
# Install syft
- uses: taiki-e/install-action@8984d603c208823d3c1a1b796f4081736f3ae3f9 # pin v2.11.6
with:
tool: [email protected]
- name: Generate SBOM
run: syft scan --config=.syft.yaml --output=spdx-json=dist/Parsec-SBOM-${{ matrix.platform }}-Wheel.spdx.json --output=cyclonedx-json=dist/Parsec-SBOM-${{ matrix.platform }}-Wheel.cyclonedx.json .
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # pin v3.1.2
with:
name: ${{ runner.os }}-${{ runner.arch }}-wheel
path: dist/
if-no-files-found: error
timeout-minutes: 5
package-linux-build-snap:
name: "🐧 Linux: 📦 Packaging (build Snap)"
needs: package-wheel
runs-on: ubuntu-20.04
env:
WHEEL_VERSION: ${{ needs.package-wheel.outputs.wheel-version }}
steps:
- name: Install snapcraft
run: sudo snap install snapcraft --classic
- name: Debug snapcraft version
run: |
set -e
echo "::warning title=Snapcraft Version::using $(snapcraft --version)"
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # pin v3.5.2
timeout-minutes: 5
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # pin v3.0.2
with:
name: ${{ runner.os }}-${{ runner.arch }}-wheel
path: dist
- name: List downloaded artifacts
run: tree dist
- name: Copy snap build configuration
working-directory: ${{ runner.temp }}
run: |
cp -Rv ${{ github.workspace }}/packaging/snap/{bin,snap} .
- name: Copy wheel configuration + python requirement
working-directory: ${{ runner.temp }}
run: |
mkdir src
WHEEL=$(ls -1 ${{ github.workspace }}/dist/parsec_cloud-*.whl)
cp -Rv $WHEEL src/
cp -v ${{ github.workspace }}/dist/core-requirements.txt src/
- name: Set snap build version
run: |
# Sed with a range specifier to only match on line 2 (where the version value is expected to be).
sed -i.back '2,/^version:/{s/^version: .*$/version: v${{ env.WHEEL_VERSION }}/}' ${{ runner.temp }}/snap/snapcraft.yaml
diff -u ${{ runner.temp }}/snap/snapcraft.yaml{.back,} || true
# Use grep as sanity check to ensure that we have the expected version value.
grep --line-number --fixed-string 'version: v${{ env.WHEEL_VERSION }}' ${{ runner.temp }}/snap/snapcraft.yaml
- name: Run snapcraft
working-directory: ${{ runner.temp }}
run: snapcraft --destructive-mode
# Install syft
- uses: taiki-e/install-action@8984d603c208823d3c1a1b796f4081736f3ae3f9 # pin v2.11.6
with:
tool: [email protected]
- name: Generate SBOM
run: syft scan --config=.syft.yaml --output=spdx-json=${{ runner.temp }}/Parsec-SBOM-linux-snap.spdx.json --output=cyclonedx-json=${{ runner.temp }}/Parsec-SBOM-linux-snap.cyclonedx.json .
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # pin v3.1.2
with:
name: ${{ runner.os }}-${{ runner.arch }}-snap
path: |
${{ runner.temp }}/parsec*.snap
${{ runner.temp }}/Parsec-SBOM-linux-snap.spdx.json
${{ runner.temp }}/Parsec-SBOM-linux-snap.cyclonedx.json
if-no-files-found: error
package-linux-test-snap:
name: "🐧 Linux: 📦 Packaging (test Snap on ${{ matrix.os }})"
needs: package-linux-build-snap
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-20.04, ubuntu-22.04 ]
steps:
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # pin v3.0.2
with:
name: ${{ runner.os }}-${{ runner.arch }}-snap
path: dist
- name: Install Snapcraft
uses: samuelmeuli/action-snapcraft@d33c176a9b784876d966f80fb1b461808edc0641 # pin v2.1.1
- name: Never trust a Snap
run: |
set -eux
sudo snap install --classic --dangerous dist/parsec*.snap
parsec.cli --version
parsec.cli --help
# Make sure snap contains core but not backend
MODULES_NOT_AVAILABLE=$(parsec.cli --help | grep -i "not available")
test "$(echo $MODULES_NOT_AVAILABLE | grep -i 'backend')"
test -z "$(echo $MODULES_NOT_AVAILABLE | grep -i 'core')"
xvfb-run parsec --diagnose
package-windows-build-installer-content:
name: "🏁 Windows: 📦 Packaging (build installer content)"
needs: package-wheel
runs-on: windows-2022
env:
WHEEL_VERSION: ${{ needs.package-wheel.outputs.wheel-version }}
steps:
- uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # pin v4.6.1
with:
python-version: ${{ env.python-version }}
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # pin v3.5.2
timeout-minutes: 5
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # pin v3.0.2
with:
name: ${{ runner.os }}-${{ runner.arch }}-wheel
path: dist
- name: List downloaded artifacts
run: Get-ChildItem -Recurse -Path dist
- uses: microsoft/setup-msbuild@1ff57057b5cfdc39105cd07a01d78e9b0ea0c14c # pin v1.3.1
- name: Build Icon overlays COM objects
run: msbuild -maxCpuCount -property:Configuration=Release .\windows-icon-handler\windows-icon-handler.sln
shell: cmd
- name: Prepare build directory
run: Copy-Item -Recurse -Path ${{ github.workspace }}\packaging\windows\* -Destination ${{ runner.temp }}
working-directory: ${{ runner.temp }}
- name: Debug ${{ runner.temp }} dir
run: Get-ChildItem -Recurse -Path ${{ runner.temp }}
- name: Freeze Parsec
run: python3 freeze_program.py ${{ github.workspace }} --wheel-it-dir ${{ github.workspace }}/dist
working-directory: ${{ runner.temp }}
- name: Debug build directory
run: Get-ChildItem -Path ${{ runner.temp }}\build
- name: Test start generated exe
shell: bash
run: ./build/parsec-*/parsec.exe --diagnose
working-directory: ${{ runner.temp }}
# Cannot do the NSIS installer part in CI given it requires to sign `parsec.exe`
- name: Artifact name
id: names
shell: bash
run: echo "archive=parsec-unsigned-v${{ env.WHEEL_VERSION }}-raw-windows-installer.zip" >> $GITHUB_OUTPUT
# The 7z man can be found here <https://linux.die.net/man/1/7z>
- name: Prepare artifact
run: |
md dist
cd build
# cspell:disable-next-line
7z a -tzip ..\${{ steps.names.outputs.archive }} `
manifest.ini `
install_files.nsh `
uninstall_files.nsh `
parsec-* `
winfsp-*
working-directory: ${{ runner.temp }}
# Install syft
- uses: taiki-e/install-action@8984d603c208823d3c1a1b796f4081736f3ae3f9 # pin v2.11.6
with:
tool: [email protected]
- name: Generate SBOM
run: syft scan --config=.syft.yaml --output=spdx-json=${{ runner.temp }}/Parsec-SBOM-windows-app.spdx.json --output=cyclonedx-json=${{ runner.temp }}/Parsec-SBOM-windows-app.cyclonedx.json .
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # pin v3.1.2
with:
name: ${{ runner.os }}-${{ runner.arch }}-installer
path: |
${{ runner.temp }}/${{ steps.names.outputs.archive }}
${{ runner.temp }}/Parsec-SBOM-windows-app.spdx.json
${{ runner.temp }}/Parsec-SBOM-windows-app.cyclonedx.json
if-no-files-found: error
package-macos-build-app:
runs-on: macos-12
name: "🍎 macOS: 📦 Packaging (build installer content)"
needs: package-wheel
env:
WHEEL_VERSION: ${{ needs.package-wheel.outputs.wheel-version }}
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # pin v3.5.2
timeout-minutes: 5
- uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # pin v4.6.1
id: setup-python
with:
python-version: ${{ env.python-version }}
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # pin v3.0.2
with:
name: ${{ runner.os }}-${{ runner.arch }}-wheel
path: dist
- name: List downloaded artifacts
run: ls -lR dist
- name: Copy packaging script
run: cp -Rv ${{ github.workspace }}/packaging/macOS/* ${{ runner.temp }}
- name: Freeze Parsec
run: python freeze_program.py ${{ github.workspace }} --wheel-it-dir ${{ github.workspace }}/dist
working-directory: ${{ runner.temp }}
- name: Debug ${{ runner.temp }} dir
run: ls -lR ${{ runner.temp }}
- name: Generate Parsec.app
run: >
tar --verbose --create --bzip2
--file parsec-unsigned-v${{ env.WHEEL_VERSION }}-macos-amd64.tar.bz2
--directory build/pyinstaller_dist parsec.app
working-directory: ${{ runner.temp }}
# Install syft
- uses: taiki-e/install-action@8984d603c208823d3c1a1b796f4081736f3ae3f9 # pin v2.11.6
with:
tool: [email protected]
- name: Generate SBOM
run: syft scan --config=.syft.yaml --output=spdx-json=${{ runner.temp }}/Parsec-SBOM-macos-app.spdx.json --output=cyclonedx-json=${{ runner.temp }}/Parsec-SBOM-macos-app.cyclonedx.json .
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # pin v3.1.2
with:
name: ${{ runner.os }}-${{ runner.arch }}-installer
path: |
${{ runner.temp }}/parsec-unsigned-v${{ env.WHEEL_VERSION }}-macos-amd64.tar.bz2
${{ runner.temp }}/Parsec-SBOM-macos-app.spdx.json
${{ runner.temp }}/Parsec-SBOM-macos-app.cyclonedx.json
if-no-files-found: error
package-macos-test-app:
runs-on: macos-${{ matrix.macos-version }}
name: "🍎 macOS: 📦 Packaging (test app on macOS-${{ matrix.macos-version }})"
needs: [ package-wheel, package-macos-build-app ]
env:
WHEEL_VERSION: ${{ needs.package-wheel.outputs.wheel-version }}
strategy:
fail-fast: false
matrix:
macos-version: [ 11, 12 ]
steps:
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # pin v3.0.2
with:
name: ${{ runner.os }}-${{ runner.arch }}-installer
path: dist
# The lsregister call forces the app's entry in the Launch Services database. Otherwise the error
# 'kLSNoExecutableErr: The executable is missing' might be raised.
- name: Test open app
run: |
set -eux
tar -xzvf dist/parsec-unsigned-v${{ env.WHEEL_VERSION }}-macos-amd64.tar.bz2 # cspell:disable-line
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -f parsec.app
open parsec.app --args --diagnose
package-android-app:
# We currently disable android building, this job need to be updated to work with `vite`.
# See tracking issue #4395 & #4419
if: false
runs-on: ubuntu-22.04
name: 🤖 Package Android app
env:
NDK_VERSION: 23.2.8568313
SDK_VERSION: 30.0.3
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # pin v3.5.2
timeout-minutes: 5
- name: Add rustup targets
run: rustup target add armv7-linux-androideabi i686-linux-android aarch64-linux-android x86_64-linux-android
timeout-minutes: 5
- name: Configure Runner environment
run: |
echo "$ANDROID_HOME/cmdline-tools/latest/bin" > $GITHUB_PATH
- name: Install dependencies for Android
run: sdkmanager --install "ndk;${{ env.NDK_VERSION }}" "build-tools;${{ env.SDK_VERSION }}"
- name: Install dependencies for ionic project
run: npm clean-install
working-directory: oxidation/client
- name: Build ionic for Android
run: |
npm run android:copy:release
working-directory: oxidation/client
- name: Build apk
run: bash ./gradlew assembleRelease
working-directory: oxidation/client/android
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # pin v3.1.2
with:
name: unsigned-android-app
path: |
oxidation/client/android/app/build/outputs/apk/release/app-release-unsigned.apk
oxidation/client/android/app/build/outputs/apk/release/output-metadata.json
if-no-files-found: error