diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml
index 3f5b1d2b..b5acc8c3 100644
--- a/.github/workflows/github-actions.yml
+++ b/.github/workflows/github-actions.yml
@@ -34,6 +34,10 @@ on:
branches:
- '**' # '*' matches zero or more characters but does not match the `/` character '**' matches zero or more of any character
+ pull_request: # we need to build on pull requests so that we can generate and upload the sbom before merging onto main/develop branches
+ branches:
+ - '**'
+
jobs:
@@ -68,35 +72,37 @@ jobs:
- name: '🏗 📦 Build, Pack & Announce New Release (if appropriate)'
shell: 'bash'
run: |
- cd "${{env.BUILD_REPOSITORY_FOLDERPATH}}/Laerdal.Scripts" \
- && \
- echo "${{env.SCL_DEPENDENCY_TRACKER_SIGNING_PRIVATE_KEY}}" > "${{env.BUILD_REPOSITORY_FOLDERPATH}}/Laerdal.Scripts/dependency_tracker_private_signing_key.ppk" \
- && \
- dotnet \
- msbuild \
- "Laerdal.Builder.targets" \
- -m:1 \
- -p:Should_Skip_MacCatalyst="false" \
- \
- -p:PackageOutputPath="${{env.BUILD_REPOSITORY_FOLDERPATH}}/Artifacts" \
- -p:Laerdal_Gradle_Path="/opt/homebrew/opt/gradle@7/bin/gradle" \
- -p:Laerdal_Source_Branch="${{env.LAERDAL_SOURCE_BRANCH}}" \
- -p:Laerdal_Repository_Path="${{env.LAERDAL_REPOSITORY_PATH}}" \
- -p:Laerdal_Github_Access_Token="${{env.SCL_GITHUB_ACCESS_TOKEN}}" \
- -p:Laerdal_Test_Results_Folderpath="${{env.BUILD_REPOSITORY_FOLDERPATH}}/TestResults" \
- \
- -p:Laerdal_CycloneCLI_Path="${{env.BUILD_REPOSITORY_FOLDERPATH}}/Laerdal.Scripts/cyclonedx" \
- -p:Laerdal_Dependency_Tracker_Api_Key="${{env.SCL_DEPENDENCY_TRACKER_API_KEY}}" \
- -p:Laerdal_Dependency_Tracker_Server_Url="${{env.SCL_DEPENDENCY_TRACKER_SERVER_URL}}" \
- -p:Laerdal_Dependency_Tracker_Private_Signing_Key_Path="${{env.BUILD_REPOSITORY_FOLDERPATH}}/Laerdal.Scripts/dependency_tracker_private_signing_key.ppk" \
- \
- -p:Laerdal_Bindings_iOS___Sdk_Version="${{env.BINDINGS_IOS___SDK_VERSION}}" \
- -p:Laerdal_Bindings_iOS___Xcode_Ide_Dev_Path="${{env.BINDINGS_IOS___XCODE_IDE_DEV_PATH}}" \
- \
- -p:Laerdal_Bindings_MacCatalyst___Sdk_Version="${{env.BINDINGS_MACCATALYST___SDK_VERSION}}" \
- -p:Laerdal_Bindings_MacCatalyst___Xcode_Ide_Dev_Path="${{env.BINDINGS_MACCATALYST___XCODE_IDE_DEV_PATH}}" \
- && \
- rm "${{env.BUILD_REPOSITORY_FOLDERPATH}}/Laerdal.Scripts/dependency_tracker_private_signing_key.ppk"
+ cd "${{env.BUILD_REPOSITORY_FOLDERPATH}}/Laerdal.Scripts" \
+ && \
+ echo "${{env.SCL_DEPENDENCY_TRACKER_API_KEY}}" > "./dependency_tracker_api_key.ppk" \
+ && \
+ echo "${{env.SCL_DEPENDENCY_TRACKER_SIGNING_PRIVATE_KEY}}" > "./dependency_tracker_private_signing_key.ppk" \
+ && \
+ dotnet \
+ msbuild \
+ "Laerdal.Builder.targets" \
+ -m:1 \
+ -p:Should_Skip_MacCatalyst="false" \
+ \
+ -p:PackageOutputPath="${{env.BUILD_REPOSITORY_FOLDERPATH}}/Artifacts" \
+ -p:Laerdal_Gradle_Path="/opt/homebrew/opt/gradle@7/bin/gradle" \
+ -p:Laerdal_Source_Branch="${{env.LAERDAL_SOURCE_BRANCH}}" \
+ -p:Laerdal_Repository_Path="${{env.LAERDAL_REPOSITORY_PATH}}" \
+ -p:Laerdal_Github_Access_Token="${{env.SCL_GITHUB_ACCESS_TOKEN}}" \
+ -p:Laerdal_Test_Results_Folderpath="${{env.BUILD_REPOSITORY_FOLDERPATH}}/TestResults" \
+ \
+ -p:Laerdal_CycloneCLI_Path="${{env.BUILD_REPOSITORY_FOLDERPATH}}/Laerdal.Scripts/cyclonedx" \
+ -p:Laerdal_Dependency_Tracker_Server_Url="${{env.SCL_DEPENDENCY_TRACKER_SERVER_URL}}" \
+ -p:Laerdal_Dependency_Tracker_Api_Key_File_Path="${{env.BUILD_REPOSITORY_FOLDERPATH}}/Laerdal.Scripts/dependency_tracker_api_key.ppk" \
+ -p:Laerdal_Dependency_Tracker_Private_Signing_Key_File_Path="${{env.BUILD_REPOSITORY_FOLDERPATH}}/Laerdal.Scripts/dependency_tracker_private_signing_key.ppk" \
+ \
+ -p:Laerdal_Bindings_iOS___Sdk_Version="${{env.BINDINGS_IOS___SDK_VERSION}}" \
+ -p:Laerdal_Bindings_iOS___Xcode_Ide_Dev_Path="${{env.BINDINGS_IOS___XCODE_IDE_DEV_PATH}}" \
+ \
+ -p:Laerdal_Bindings_MacCatalyst___Sdk_Version="${{env.BINDINGS_MACCATALYST___SDK_VERSION}}" \
+ -p:Laerdal_Bindings_MacCatalyst___Xcode_Ide_Dev_Path="${{env.BINDINGS_MACCATALYST___XCODE_IDE_DEV_PATH}}" \
+ && \
+ rm "./dependency_tracker_private_signing_key.ppk" "./dependency_tracker_api_key.ppk"
- name: '📡 Publish Test Results' # https://github.com/marketplace/actions/publish-test-results
uses: 'EnricoMi/publish-unit-test-result-action/macos@v2'
diff --git a/Laerdal.McuMgr.sln b/Laerdal.McuMgr.sln
index 8252dce1..1b1732cf 100644
--- a/Laerdal.McuMgr.sln
+++ b/Laerdal.McuMgr.sln
@@ -11,6 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Misc", "_Misc", "{2459FC0F
global.json = global.json
Laerdal.SetupBuildEnvironment.sh = Laerdal.Scripts\Laerdal.SetupBuildEnvironment.sh
.github\workflows\github-actions.yml = .github\workflows\github-actions.yml
+ Laerdal.Scripts\Laerdal.GenerateSignAndUploadSbom.sh = Laerdal.Scripts\Laerdal.GenerateSignAndUploadSbom.sh
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Laerdal.McuMgr", "Laerdal.McuMgr\Laerdal.McuMgr.csproj", "{4E2952A5-394E-4184-8E12-F2D5342A43B2}"
diff --git a/Laerdal.Scripts/Laerdal.Builder.targets b/Laerdal.Scripts/Laerdal.Builder.targets
index d1effe08..778ac892 100644
--- a/Laerdal.Scripts/Laerdal.Builder.targets
+++ b/Laerdal.Scripts/Laerdal.Builder.targets
@@ -50,7 +50,9 @@
- true
+ true
+ true
+ true
false
@@ -63,11 +65,13 @@
-
+
gradle
$(BUILD_SOURCEBRANCH)
$(BUILD_REPOSITORY_NAME)
- True
+
+ True
+ True
$([System.IO.Path]::Combine($(Laerdal_RootDirectory_Folderpath), `Laerdal.McuMgr`, `Laerdal.McuMgr.csproj`))
$([System.IO.Path]::Combine($(Laerdal_RootDirectory_Folderpath), `Laerdal.McuMgr.Bindings.iOS`, `Laerdal.McuMgr.Bindings.iOS.csproj`))
@@ -312,17 +316,16 @@
WorkingDirectory="$(Laerdal_RootDirectory_Folderpath)"/>
-
+
-
-
+ Condition=" '$(Laerdal_Should_Generate_and_Upload_Sbom)' == 'True' "
+ AfterTargets="BuildProjects">
-
-
-
-
+
+
+
+
+
@@ -340,39 +343,28 @@
<_Laerdal_Command___Generate_SBOM>$(_Laerdal_Command___Generate_SBOM) --output "$(PackageOutputPath)"
<_Laerdal_Command___Generate_SBOM>$(_Laerdal_Command___Generate_SBOM) --set-version "$(Laerdal_Version_Full)"
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_Laerdal_Command___Upload_SBOM>$(_Laerdal_Command___Upload_SBOM) curl "$(Laerdal_Dependency_Tracker_Server_Url)"
- <_Laerdal_Command___Upload_SBOM>$(_Laerdal_Command___Upload_SBOM) --location
- <_Laerdal_Command___Upload_SBOM>$(_Laerdal_Command___Upload_SBOM) --request "POST"
- <_Laerdal_Command___Upload_SBOM>$(_Laerdal_Command___Upload_SBOM) --header "Content-Type: multipart/form-data"
- <_Laerdal_Command___Upload_SBOM>$(_Laerdal_Command___Upload_SBOM) --header "X-API-Key: $(Laerdal_Dependency_Tracker_Api_Key)"
- <_Laerdal_Command___Upload_SBOM>$(_Laerdal_Command___Upload_SBOM) --form "autoCreate=true"
- <_Laerdal_Command___Upload_SBOM>$(_Laerdal_Command___Upload_SBOM) --form "projectVersion=$(Laerdal_Version_Full)"
+ <_Laerdal_Sbom_Script_Parameters>$(_Laerdal_Sbom_Script_Parameters) --project-version "$(Laerdal_Version_Assembly)"
+ <_Laerdal_Sbom_Script_Parameters>$(_Laerdal_Sbom_Script_Parameters) --output-directory-path "$(PackageOutputPath)"
+ <_Laerdal_Sbom_Script_Parameters>$(_Laerdal_Sbom_Script_Parameters) --sbom-signing-key-file-path "$(Laerdal_Dependency_Tracker_Private_Signing_Key_File_Path)"
+
+ <_Laerdal_Sbom_Script_Parameters>$(_Laerdal_Sbom_Script_Parameters) --dependency-tracker-url "$(Laerdal_Dependency_Tracker_Server_Url)"
+ <_Laerdal_Sbom_Script_Parameters>$(_Laerdal_Sbom_Script_Parameters) --dependency-tracker-api-key-file-path "$(Laerdal_Dependency_Tracker_Api_Key_File_Path)"
+
+ <_Laerdal_Sbom_Script_Parameters>$(_Laerdal_Sbom_Script_Parameters) --csproj-classifier "Library"
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/Laerdal.Scripts/Laerdal.GenerateSignAndUploadSbom.sh b/Laerdal.Scripts/Laerdal.GenerateSignAndUploadSbom.sh
new file mode 100644
index 00000000..94b41001
--- /dev/null
+++ b/Laerdal.Scripts/Laerdal.GenerateSignAndUploadSbom.sh
@@ -0,0 +1,248 @@
+#!/bin/bash
+
+# set -x
+
+declare project_name=""
+declare project_version=""
+
+declare parent_project_name=""
+declare parent_project_version=""
+
+declare csproj_file_path=""
+declare csproj_classifier=""
+declare output_directory_path=""
+declare output_sbom_file_name=""
+declare sbom_signing_key_file_path=""
+
+declare dependency_tracker_url=""
+declare dependency_tracker_api_key_file_path=""
+
+
+function parse_arguments() {
+
+ while [[ $# -gt 0 ]]; do
+ case $1 in
+
+ --project-name)
+ project_name="$2"
+ shift
+ ;;
+
+ --project-version)
+ project_version="$2"
+ shift
+ ;;
+
+ --parent-project-name)
+ parent_project_name="$2"
+ shift
+ ;;
+
+ --parent-project-version)
+ parent_project_version="$2"
+ shift
+ ;;
+
+ --csproj-file-path)
+ csproj_file_path="$2"
+ shift
+ ;;
+
+ --csproj-classifier)
+ csproj_classifier="$2"
+ shift
+ ;;
+
+ --output-directory-path)
+ output_directory_path="$2"
+ shift
+ ;;
+
+ --output-sbom-file-name)
+ output_sbom_file_name="$2"
+ shift
+ ;;
+
+ --sbom-signing-key-file-path)
+ sbom_signing_key_file_path="$2"
+ shift
+ ;;
+
+ --dependency-tracker-url)
+ dependency_tracker_url="$2"
+ shift
+ ;;
+
+ --dependency-tracker-api-key-file-path)
+ dependency_tracker_api_key_file_path="$2"
+ shift
+ ;;
+
+ *)
+ echo "Unknown option: $1"
+ usage
+ exit 1
+ ;;
+ esac
+
+ shift
+ done
+
+ if [[ -z ${project_name} ]]; then
+ echo "Specifying --project-name is mandatory!"
+ usage
+ exit 1
+ fi
+
+ if [[ -z ${project_version} ]]; then
+ echo "Specifying --project-version is mandatory!"
+ usage
+ exit 1
+ fi
+
+ # if [[ -z ${parent_project_name} ]]; then this is optional
+ # ...
+
+ # if [[ -z ${parent_project_version} ]]; then this is optional
+ # ...
+
+ if [[ -n ${parent_project_name} && -z ${parent_project_version} ]]; then
+ echo "Specifying --parent-project-version is mandatory when --parent-project-name has been used!"
+ usage
+ exit 1
+ fi
+
+ if [[ -z ${csproj_file_path} ]]; then
+ echo "Specifying --csproj-file-path is mandatory!"
+ usage
+ exit 1
+ fi
+
+ if [[ -z ${csproj_classifier} ]]; then
+ echo "Specifying --csproj-classifier is mandatory!"
+ usage
+ exit 1
+ fi
+
+ if [[ -z ${output_directory_path} ]]; then
+ echo "Specifying --output-directory-path is mandatory!"
+ usage
+ exit 1
+ fi
+
+ if [[ -z ${output_sbom_file_name} ]]; then
+ echo "Specifying --output-sbom-file-name is mandatory!"
+ usage
+ exit 1
+ fi
+
+ if [[ -z ${sbom_signing_key_file_path} ]]; then
+ echo "Specifying --sbom-signing-key-file-path is mandatory!"
+ usage
+ exit 1
+ fi
+
+ if [[ -z ${dependency_tracker_url} ]]; then
+ echo "Specifying --dependency-tracker-url is mandatory!"
+ usage
+ exit 1
+ fi
+
+ if [[ -z ${dependency_tracker_api_key_file_path} ]]; then
+ echo "Specifying --dependency-tracker-api-key-file-path is mandatory!"
+ usage
+ exit 1
+ fi
+}
+
+function usage() {
+ local -r script_name=$(basename "$0")
+
+ echo "Usage: ${script_name} --project-name --project-version [--parent-project-name --parent-project-version ] --csproj-file-path --csproj-file-path --output-directory-path --output-sbom-file-name --sbom-signing-key-file-path --dependency-tracker-url --dependency-tracker-api-key-file-path "
+}
+
+function generate_sign_and_upload_sbom() {
+ set -x
+
+ # GENERATE SBOM
+ dotnet-CycloneDX "${csproj_file_path}" \
+ --exclude-dev \
+ --include-project-references \
+ \
+ --output "${output_directory_path}" \
+ --set-type "${csproj_classifier}" \
+ --set-version "${project_version}" \
+ \
+ --filename "${output_sbom_file_name}"
+ declare exitCode=$?
+ if [ ${exitCode} != 0 ]; then
+ echo "##vso[task.logissue type=error]Failed to generate the SBOM!"
+ exit 10
+ fi
+
+
+
+ # SIGN SBOM todo figure out why this doesnt actually sign anything on windows even though on macos it works as intended
+ declare -r bom_file_path="${output_directory_path}/${output_sbom_file_name}"
+ ./cyclonedx sign bom \
+ "${bom_file_path}" \
+ --key-file "${sbom_signing_key_file_path}"
+ declare exitCode=$?
+ if [ ${exitCode} != 0 ]; then
+ echo "##vso[task.logissue type=error]Singing the SBOM failed!"
+ exit 20
+ fi
+ echo -e "\n\n"
+ tail "${bom_file_path}"
+ echo -e "\n\n"
+
+
+
+ # UPLOAD SBOM
+ declare optional_parent_project_name_parameter=""
+ if [[ -n ${parent_project_name} ]]; then
+ optional_parent_project_name_parameter="--form parentName=${parent_project_name}"
+ fi
+
+ declare optional_parent_project_version_parameter=""
+ if [[ -n ${parent_project_version} ]]; then
+ optional_parent_project_version_parameter="--form parentVersion=${parent_project_version}"
+ fi
+
+
+ declare -r http_response_code=$( \
+ curl "${dependency_tracker_url}" \
+ --location \
+ --request "POST" \
+ \
+ --header "Content-Type: multipart/form-data" \
+ --header "X-API-Key: $(cat "${dependency_tracker_api_key_file_path}")" \
+ \
+ --form "bom=@${bom_file_path}" \
+ --form "autoCreate=true" \
+ \
+ --form "projectName=${project_name}" \
+ --form "projectVersion=${project_version}" \
+ \
+ ${optional_parent_project_name_parameter} \
+ ${optional_parent_project_version_parameter} \
+ \
+ -w "%{http_code}" \
+ )
+ declare exitCode=$?
+ set +x
+
+ echo "** Curl sbom-uploading HTTP Response Code: ${http_response_code}"
+
+ if [ ${exitCode} != 0 ]; then
+ echo "##vso[task.logissue type=error]SBOM Uploading failed!"
+ exit 30
+ fi
+}
+
+function main() {
+ parse_arguments "$@"
+ generate_sign_and_upload_sbom
+}
+
+main "$@"