TODO add docs, refactor pipeline.
name: .NET and npm build
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x
- name: Restore dependencies
run: dotnet restore
- name: npm setup
working-directory: ui
run: npm install
- name: ui-build
working-directory: ui
run: npm run build
- name: Build
run: dotnet build --no-restore
- name: Test
run: dotnet test --no-build --verbosity normal
- name: Generate SBOM (SPDX 3)
run: |
curl -Lo $RUNNER_TEMP/sbom-tool https://github.com/microsoft/sbom-tool/releases/latest/download/sbom-tool-linux-x64
chmod +x $RUNNER_TEMP/sbom-tool
$RUNNER_TEMP/sbom-tool generate \
-b ./ \
-bc ./ \
-pn mysolution \
-pv "1.0.0" \
-ps damienbod \
-mi SPDX:3.0
- name: Upload SBOM artifact
uses: actions/upload-artifact@v4
with:
name: sbom
path: ./_manifest/
- name: Get OAuth2 access token
# Required secret: OAUTH_CLIENT_SECRET
# Add this secret in the repository Settings > Secrets and variables > Actions
id: get_token
env:
OAUTH_CLIENT_SECRET: ${{ secrets.OAUTH_CLIENT_SECRET }}
run: |
TOKEN_RESPONSE=$(curl -s -X POST \
"https://organisational-mgmt.wonderfulsmoke-b96b7f1a.switzerlandnorth.azurecontainerapps.io/api/connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "client_id=4b685cd2-d4c3-4cef-b2e4-1f5275be77df" \
--data-urlencode "scope=backend-for-frontend-vuejs-dotnet" \
--data-urlencode "client_secret=${OAUTH_CLIENT_SECRET}")
ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.access_token // empty')
if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
echo "Failed to obtain access token. Response: $(echo "$TOKEN_RESPONSE" | jq 'del(.access_token)')"
exit 1
fi
echo "::add-mask::$ACCESS_TOKEN"
echo "access_token=$ACCESS_TOKEN" >> $GITHUB_OUTPUT
- name: Upload SBOM to dependency risk API
# Endpoint determined from:
# https://organisational-mgmt.wonderfulsmoke-b96b7f1a.switzerlandnorth.azurecontainerapps.io/openapi/v1/openapi.json
# SbomType is set to "Spdx3x" to match the SPDX 3.1 format generated above.
# Note: --rawfile and @file are used instead of shell variables to avoid hitting
# the OS ARG_MAX limit when the SBOM JSON is large (fixes "Argument list too long").
env:
ACCESS_TOKEN: ${{ steps.get_token.outputs.access_token }}
run: |
SBOM_FILE=./_manifest/spdx_3.0/manifest.spdx.json
if [ ! -s "$SBOM_FILE" ]; then
echo "SBOM file not found or empty: $SBOM_FILE"
exit 1
fi
# Use --rawfile to read the SBOM from disk rather than passing its content
# as a command-line argument, which would exceed ARG_MAX for large SBOMs.
# --rawfile (like --arg) binds the file content as a JSON string, matching
# the API contract where Sbom is a string field, not an embedded JSON object.
jq -n \
--arg solutionName "backend-for-frontend-vue-js-dotnet" \
--argjson organisationId 1 \
--arg sbomId "bff-vuejs-dotnet" \
--arg sbomType "Spdx3x" \
--rawfile sbom "$SBOM_FILE" \
'{SolutionName: $solutionName, OrganisationId: $organisationId, SbomId: $sbomId, SbomType: $sbomType, Sbom: $sbom}' \
> /tmp/sbom_payload.json
HTTP_STATUS=$(curl -s -o /tmp/sbom_upload_response.json -w "%{http_code}" -X POST \
"https://organisational-mgmt.wonderfulsmoke-b96b7f1a.switzerlandnorth.azurecontainerapps.io/api/sbom" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
--data @/tmp/sbom_payload.json)
echo "HTTP Status: $HTTP_STATUS"
cat /tmp/sbom_upload_response.json
if [ "$HTTP_STATUS" -lt 200 ] || [ "$HTTP_STATUS" -ge 300 ]; then
echo "SBOM upload failed with HTTP status $HTTP_STATUS"
exit 1
fi