@@ -365,12 +365,250 @@ jobs:
365365 done
366366 exit $EXIT_CODE
367367
368+ # Active-entity tests run serially in their own slot AFTER integration-test to avoid
369+ # fixture-collision with sibling matrix entries (all touch the same Books/author='author' rows).
370+ active-entity-test :
371+ environment : dev
372+ needs : integration-test
373+ runs-on : ubuntu-latest
374+ strategy :
375+ fail-fast : false
376+ max-parallel : 1
377+ matrix :
378+ tokenFlow : [namedUser, technicalUser]
379+ testClass :
380+ - IntegrationTest_ActiveEntity
381+ - IntegrationTest_ActiveEntity_MultipleFacet
382+ - IntegrationTest_ActiveEntity_Chapters_MultipleFacet
383+ env :
384+ FILE_URL : ${{ 'http://www.eicar.org/download/eicar.com.txt' }}
385+ DOWNLOAD_PATH : ${{ 'sdm/eicar.com.txt' }}
386+ steps :
387+ - name : Checkout repository 📁
388+ uses : actions/checkout@v6
389+
390+ - name : Set up Java 21 ☕
391+ uses : actions/setup-java@v3
392+ with :
393+ java-version : 21
394+ distribution : ' temurin'
395+ cache : ' maven'
396+
397+ - name : Cache CF CLI 📦
398+ id : cache-cf-cli
399+ uses : actions/cache@v4
400+ with :
401+ path : /usr/bin/cf8
402+ key : cf-cli-v8-${{ runner.os }}
403+
404+ - name : Install Cloud Foundry CLI 🔧
405+ if : steps.cache-cf-cli.outputs.cache-hit != 'true'
406+ run : |
407+ echo "🔄 Installing Cloud Foundry CLI..."
408+ wget -q -O - https://packages.cloudfoundry.org/debian/cli.cloudfoundry.org.key | sudo apt-key add -
409+ echo "deb https://packages.cloudfoundry.org/debian stable main" | sudo tee /etc/apt/sources.list.d/cloudfoundry-cli.list
410+ sudo apt-get update
411+ sudo apt-get install cf8-cli
412+
413+ - name : Install jq 📦
414+ run : |
415+ if ! command -v jq &> /dev/null; then
416+ sudo apt-get update && sudo apt-get install -y jq
417+ fi
418+
419+ - name : Login to Cloud Foundry 🔑
420+ env :
421+ CF_API : ${{ secrets.CF_API }}
422+ CF_USER : ${{ secrets.CF_USER }}
423+ CF_PASSWORD : ${{ secrets.CF_PASSWORD }}
424+ CF_ORG : ${{ secrets.CF_ORG }}
425+ CF_SPACE : ${{ secrets.CF_SPACE }}
426+ run : |
427+ set +x
428+ echo "::add-mask::$CF_API"
429+ echo "::add-mask::$CF_USER"
430+ echo "::add-mask::$CF_PASSWORD"
431+ echo "::add-mask::$CF_ORG"
432+ echo "::add-mask::$CF_SPACE"
433+ echo "🔄 Logging in to Cloud Foundry using space: $CF_SPACE"
434+ cf login -a "$CF_API" \
435+ -u "$CF_USER" \
436+ -p "$CF_PASSWORD" \
437+ -o "$CF_ORG" \
438+ -s $CF_SPACE > /dev/null
439+
440+ - name : Fetch and Escape Client Details for single tenant 🔍
441+ id : fetch_credentials
442+ run : |
443+ echo "🔄 Fetching client details for single tenant..."
444+ service_instance_guid=$(cf service demoappjava-public-uaa --guid)
445+ if [ -z "$service_instance_guid" ]; then
446+ echo "❌ Error: Unable to retrieve service instance GUID"; exit 1;
447+ fi
448+ bindings_response=$(cf curl "/v3/service_credential_bindings?service_instance_guids=${service_instance_guid}")
449+ binding_guid=$(echo "$bindings_response" | jq -r '.resources[0].guid')
450+ if [ -z "$binding_guid" ]; then
451+ echo "❌ Error: Unable to retrieve binding GUID"; exit 1;
452+ fi
453+ binding_details=$(cf curl "/v3/service_credential_bindings/${binding_guid}/details")
454+ clientSecret=$(echo "$binding_details" | jq -r '.credentials.clientsecret')
455+ if [ -z "$clientSecret" ] || [ "$clientSecret" == "null" ]; then
456+ echo "❌ Error: clientSecret is not set or is null"; exit 1;
457+ fi
458+ escapedClientSecret=$(echo "$clientSecret" | sed 's/\$/\\$/g')
459+ echo "::add-mask::$escapedClientSecret"
460+ clientID=$(echo "$binding_details" | jq -r '.credentials.clientid')
461+ if [ -z "$clientID" ] || [ "$clientID" == "null" ]; then
462+ echo "❌ Error: clientID is not set or is null"; exit 1;
463+ fi
464+ echo "::add-mask::$clientID"
465+ echo "CLIENT_SECRET=$escapedClientSecret" >> $GITHUB_OUTPUT
466+ echo "CLIENT_ID=$clientID" >> $GITHUB_OUTPUT
467+ echo "✅ Client details fetched successfully!"
468+
469+ - name : Fetch and Escape SDM CMIS Credentials 🔍
470+ id : fetch_credentials_cmis
471+ run : |
472+ echo "🔄 Fetching SDM CMIS credentials from CF service binding..."
473+ service_instance_guid=$(cf service sdm --guid)
474+ if [ -z "$service_instance_guid" ]; then
475+ echo "❌ Error: Unable to retrieve SDM service instance GUID"; exit 1;
476+ fi
477+ bindings_response=$(cf curl "/v3/service_credential_bindings?service_instance_guids=${service_instance_guid}")
478+ app_guid=$(cf app demoappjava-srv --guid)
479+ binding_guid=$(echo "$bindings_response" | jq -r \
480+ --arg app_guid "$app_guid" \
481+ '.resources[] | select(.relationships.app.data.guid == $app_guid) | .guid' | head -1)
482+ if [ -z "$binding_guid" ]; then
483+ echo "❌ Error: Unable to retrieve SDM binding GUID for demoappjava-srv"; exit 1;
484+ fi
485+ binding_details=$(cf curl "/v3/service_credential_bindings/${binding_guid}/details")
486+ cmis_client_secret=$(echo "$binding_details" | jq -r '.credentials.uaa.clientsecret // .credentials.clientsecret // empty')
487+ if [ -z "$cmis_client_secret" ] || [ "$cmis_client_secret" == "null" ]; then
488+ echo "❌ Error: SDM clientsecret is not set or is null"; exit 1;
489+ fi
490+ echo "::add-mask::$cmis_client_secret"
491+ cmis_client_id=$(echo "$binding_details" | jq -r '.credentials.uaa.clientid // .credentials.clientid // empty')
492+ if [ -z "$cmis_client_id" ] || [ "$cmis_client_id" == "null" ]; then
493+ echo "❌ Error: SDM clientid is not set or is null"; exit 1;
494+ fi
495+ echo "::add-mask::$cmis_client_id"
496+ cmis_url=$(echo "$binding_details" | jq -r '.credentials.uri // .credentials.endpoints.ecm_service // .credentials.url // empty')
497+ if [ -z "$cmis_url" ]; then
498+ echo "❌ Error: SDM CMIS URL not found in binding details"; exit 1;
499+ fi
500+ echo "::add-mask::$cmis_url"
501+ printf 'CMIS_CLIENT_SECRET=%s\n' "$cmis_client_secret" >> $GITHUB_OUTPUT
502+ printf 'CMIS_CLIENT_ID=%s\n' "$cmis_client_id" >> $GITHUB_OUTPUT
503+ printf 'CMIS_URL=%s\n' "$cmis_url" >> $GITHUB_OUTPUT
504+ echo "✅ SDM CMIS credentials fetched successfully!"
505+
506+ - name : Run active-entity integration tests 🎯 (${{ matrix.tokenFlow }} - ${{ matrix.testClass }})
507+ env :
508+ CLIENT_SECRET : ${{ steps.fetch_credentials.outputs.CLIENT_SECRET }}
509+ CLIENT_ID : ${{ steps.fetch_credentials.outputs.CLIENT_ID }}
510+ CMIS_CLIENT_ID : ${{ steps.fetch_credentials_cmis.outputs.CMIS_CLIENT_ID }}
511+ CMIS_CLIENT_SECRET : ${{ steps.fetch_credentials_cmis.outputs.CMIS_CLIENT_SECRET }}
512+ CMIS_URL_FROM_CF : ${{ steps.fetch_credentials_cmis.outputs.CMIS_URL }}
513+ CF_ORG : ${{ secrets.CF_ORG }}
514+ CAPAUTH_URL : ${{ secrets.CAPAUTH_URL }}
515+ CF_USER : ${{ secrets.CF_USER }}
516+ CF_PASSWORD : ${{ secrets.CF_PASSWORD }}
517+ NOSDMROLEUSERNAME : ${{ secrets.NOSDMROLEUSERNAME }}
518+ NOSDMROLEUSERPASSWORD : ${{ secrets.NOSDMROLEUSERPASSWORD }}
519+ VERSIONEDREPOSITORYID : ${{ secrets.VERSIONEDREPOSITORYID }}
520+ VIRUSSCANREPOSITORYID : ${{ secrets.VIRUSSCANREPOSITORYID }}
521+ DEFAULTREPOSITORYID : ${{ secrets.DEFAULTREPOSITORYID }}
522+ CF_SPACE : ${{ secrets.CF_SPACE }}
523+ run : |
524+ set +x
525+ echo "🚀 Starting active-entity integration tests for ${{ matrix.tokenFlow }} - ${{ matrix.testClass }}..."
526+ set -e
527+ PROPERTIES_FILE="sdm/src/test/resources/credentials.properties"
528+ appUrl="$CF_ORG-$CF_SPACE-demoappjava-srv.cfapps.eu12.hana.ondemand.com"
529+ authUrl="$CAPAUTH_URL"
530+ clientID="$CLIENT_ID"
531+ clientSecret="$CLIENT_SECRET"
532+ username="$CF_USER"
533+ password="$CF_PASSWORD"
534+ noSDMRoleUsername="$NOSDMROLEUSERNAME"
535+ noSDMRoleUserPassword="$NOSDMROLEUSERPASSWORD"
536+ versionedRepositoryID="$VERSIONEDREPOSITORYID"
537+ virusScanRepositoryID="$VIRUSSCANREPOSITORYID"
538+ defaultRepositoryID="$DEFAULTREPOSITORYID"
539+ CMIS_URL="$CMIS_URL_FROM_CF"
540+ cmisClientID="$CMIS_CLIENT_ID"
541+ cmisClientSecret="$CMIS_CLIENT_SECRET"
542+ echo "::add-mask::$clientSecret"
543+ echo "::add-mask::$clientID"
544+ echo "::add-mask::$username"
545+ echo "::add-mask::$password"
546+ echo "::add-mask::$noSDMRoleUsername"
547+ echo "::add-mask::$noSDMRoleUserPassword"
548+ echo "::add-mask::$versionedRepositoryID"
549+ echo "::add-mask::$virusScanRepositoryID"
550+ echo "::add-mask::$defaultRepositoryID"
551+ echo "::add-mask::$CMIS_URL"
552+ echo "::add-mask::$cmisClientID"
553+ echo "::add-mask::$cmisClientSecret"
554+ if [ -z "$appUrl" ]; then echo "❌ Error: appUrl is not set"; exit 1; fi
555+ if [ -z "$authUrl" ]; then echo "❌ Error: authUrl is not set"; exit 1; fi
556+ if [ -z "$clientID" ]; then echo "❌ Error: clientID is not set"; exit 1; fi
557+ if [ -z "$clientSecret" ]; then echo "❌ Error: clientSecret is not set"; exit 1; fi
558+ if [ -z "$username" ]; then echo "❌ Error: username is not set"; exit 1; fi
559+ if [ -z "$password" ]; then echo "❌ Error: password is not set"; exit 1; fi
560+ if [ -z "$noSDMRoleUsername" ]; then echo "❌ Error: noSDMRoleUsername is not set"; exit 1; fi
561+ if [ -z "$noSDMRoleUserPassword" ]; then echo "❌ Error: noSDMRoleUserPassword is not set"; exit 1; fi
562+ if [ -z "$versionedRepositoryID" ]; then echo "❌ Error: versionedRepositoryID is not set"; exit 1; fi
563+ if [ -z "$virusScanRepositoryID" ]; then echo "❌ Error: virusScanRepositoryID is not set"; exit 1; fi
564+ if [ -z "$defaultRepositoryID" ]; then echo "❌ Error: defaultRepositoryID is not set"; exit 1; fi
565+ if [ -z "$CMIS_URL" ]; then echo "❌ Error: CMIS_URL is not set"; exit 1; fi
566+ if [ -z "$cmisClientID" ]; then echo "❌ Error: cmisClientID is not set"; exit 1; fi
567+ if [ -z "$cmisClientSecret" ]; then echo "❌ Error: cmisClientSecret is not set"; exit 1; fi
568+ cat > "$PROPERTIES_FILE" <<EOL
569+ appUrl=$appUrl
570+ authUrl=$authUrl
571+ clientID=$clientID
572+ clientSecret=$clientSecret
573+ username=$username
574+ password=$password
575+ noSDMRoleUsername=$noSDMRoleUsername
576+ noSDMRoleUserPassword=$noSDMRoleUserPassword
577+ versionedRepositoryID=$versionedRepositoryID
578+ virusScanRepositoryID=$virusScanRepositoryID
579+ defaultRepositoryID=$defaultRepositoryID
580+ CMIS_URL=$CMIS_URL
581+ cmisClientID=$cmisClientID
582+ cmisClientSecret=$cmisClientSecret
583+ EOL
584+ echo "🎯 Running active-entity Maven integration tests for ${{ matrix.tokenFlow }} - ${{ matrix.testClass }}..."
585+ MAX_RETRIES=3
586+ ATTEMPT=0
587+ EXIT_CODE=1
588+ while [ $ATTEMPT -lt $MAX_RETRIES ]; do
589+ ATTEMPT=$((ATTEMPT + 1))
590+ echo "🔄 Attempt $ATTEMPT of $MAX_RETRIES..."
591+ if mvn clean verify -P integration-tests -DtokenFlow=${{ matrix.tokenFlow }} -DtenancyModel=single -DskipUnitTests -Dfailsafe.includes="**/${{ matrix.testClass }}.java"; then
592+ echo "✅ Tests passed on attempt $ATTEMPT!"
593+ EXIT_CODE=0
594+ break
595+ else
596+ if [ $ATTEMPT -lt $MAX_RETRIES ]; then
597+ echo "⚠️ Attempt $ATTEMPT failed. Retrying in 30 seconds..."
598+ sleep 30
599+ else
600+ echo "❌ All $MAX_RETRIES attempts failed for ${{ matrix.tokenFlow }} - ${{ matrix.testClass }}."
601+ fi
602+ fi
603+ done
604+ exit $EXIT_CODE
605+
368606 # Single-job setup: switch CF app to versioned repo BEFORE matrix tests run.
369607 # Avoids race condition where parallel matrix entries try to restage the same app simultaneously.
370608 versioned-setup :
371609 environment : dev
372610 runs-on : ubuntu-latest
373- needs : integration -test
611+ needs : active-entity -test
374612 steps :
375613 - name : Cache CF CLI 📦
376614 id : cache-cf-cli
@@ -1195,17 +1433,19 @@ jobs:
11951433 test-summary :
11961434 environment : dev
11971435 runs-on : ubuntu-latest
1198- needs : [integration-test, versioned-test, virusscan-test, virusscan-cleanup, repospecific-test]
1436+ needs : [integration-test, active-entity-test, versioned-test, virusscan-test, virusscan-cleanup, repospecific-test]
11991437 if : " !cancelled()"
12001438 steps :
12011439 - name : Check test results 📋
12021440 run : |
12031441 echo "Integration test: ${{ needs.integration-test.result }}"
1442+ echo "Active entity test: ${{ needs.active-entity-test.result }}"
12041443 echo "Versioned test: ${{ needs.versioned-test.result }}"
12051444 echo "Virus scan test: ${{ needs.virusscan-test.result }}"
12061445 echo "Virusscan cleanup: ${{ needs.virusscan-cleanup.result }}"
12071446 echo "Repo-specific test: ${{ needs.repospecific-test.result }} (disabled is OK)"
12081447 if [ "${{ needs.integration-test.result }}" == "success" ] && \
1448+ [ "${{ needs.active-entity-test.result }}" == "success" ] && \
12091449 [ "${{ needs.versioned-test.result }}" == "success" ] && \
12101450 [ "${{ needs.virusscan-test.result }}" == "success" ] && \
12111451 [ "${{ needs.virusscan-cleanup.result }}" == "success" ]; then
0 commit comments