Multi Tenancy Integration Test π #182
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Multi Tenancy Integration Test π | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| cf_space: | |
| description: 'Specify the Cloud Foundry space to run integration tests on' | |
| required: true | |
| default: developcap | |
| branch_name: | |
| description: 'Specify the branch to use for integration tests' | |
| required: true | |
| default: develop | |
| jobs: | |
| # Parallel integration tests using matrix strategy | |
| integration-test: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| tokenFlow: [namedUser, technicalUser] | |
| tenant: [TENANT1, TENANT2] | |
| testClass: | |
| - IntegrationTest_SingleFacet | |
| - IntegrationTest_MultipleFacet | |
| - IntegrationTest_Chapters_MultipleFacet | |
| steps: | |
| - name: Checkout repository β | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.event.inputs.branch_name }} | |
| - name: Set up Java 17 β | |
| uses: actions/setup-java@v3 | |
| with: | |
| java-version: 17 | |
| distribution: 'temurin' | |
| cache: 'maven' | |
| - name: Cache CF CLI π¦ | |
| id: cache-cf-cli | |
| uses: actions/cache@v4 | |
| with: | |
| path: /usr/bin/cf8 | |
| key: cf-cli-v8-${{ runner.os }} | |
| - name: Install Cloud Foundry CLI and jq π¦ | |
| if: steps.cache-cf-cli.outputs.cache-hit != 'true' | |
| run: | | |
| echo "π§ Installing Cloud Foundry CLI..." | |
| wget -q -O - https://packages.cloudfoundry.org/debian/cli.cloudfoundry.org.key | sudo apt-key add - | |
| echo "deb https://packages.cloudfoundry.org/debian stable main" | sudo tee /etc/apt/sources.list.d/cloudfoundry-cli.list | |
| sudo apt-get update | |
| sudo apt-get install cf8-cli | |
| - name: Install jq π¦ | |
| run: | | |
| if ! command -v jq &> /dev/null; then | |
| sudo apt-get update && sudo apt-get install -y jq | |
| fi | |
| - name: Determine Cloud Foundry Space π | |
| id: determine_space | |
| run: | | |
| if [ "${{ github.event.inputs.cf_space }}" == "developcap" ]; then | |
| space="${{ secrets.CF_SPACE }}" | |
| else | |
| space="${{ github.event.inputs.cf_space }}" | |
| fi | |
| echo "π Space determined: $space" | |
| echo "space=$space" >> $GITHUB_OUTPUT | |
| - name: Login to Cloud Foundry π | |
| run: | | |
| echo "π Logging in to Cloud Foundry using space: ${{ steps.determine_space.outputs.space }}" | |
| cf login -a ${{ secrets.CF_API }} \ | |
| -u ${{ secrets.CF_USER }} \ | |
| -p ${{ secrets.CF_PASSWORD }} \ | |
| -o ${{ secrets.CF_ORG }} \ | |
| -s ${{ steps.determine_space.outputs.space }} | |
| - name: Fetch and Escape Client Details for single tenant π | |
| id: fetch_credentials | |
| run: | | |
| echo "Fetching client details for single tenant..." | |
| service_instance_guid=$(cf service demoappjava-public-uaa --guid) | |
| if [ -z "$service_instance_guid" ]; then | |
| echo "β Error: Unable to retrieve service instance GUID"; exit 1; | |
| fi | |
| bindings_response=$(cf curl "/v3/service_credential_bindings?service_instance_guids=${service_instance_guid}") | |
| binding_guid=$(echo "$bindings_response" | jq -r '.resources[0].guid') | |
| if [ -z "$binding_guid" ]; then | |
| echo "β Error: Unable to retrieve binding GUID"; exit 1; | |
| fi | |
| binding_details=$(cf curl "/v3/service_credential_bindings/${binding_guid}/details") | |
| clientSecret=$(echo "$binding_details" | jq -r '.credentials.clientsecret') | |
| if [ -z "$clientSecret" ] || [ "$clientSecret" == "null" ]; then | |
| echo "β Error: clientSecret is not set or is null"; exit 1; | |
| fi | |
| escapedClientSecret=$(echo "$clientSecret" | sed 's/\$/\\$/g') | |
| echo "::add-mask::$escapedClientSecret" | |
| clientID=$(echo "$binding_details" | jq -r '.credentials.clientid') | |
| if [ -z "$clientID" ] || [ "$clientID" == "null" ]; then | |
| echo "β Error: clientID is not set or is null"; exit 1; | |
| fi | |
| echo "::add-mask::$clientID" | |
| echo "CLIENT_SECRET=$escapedClientSecret" >> $GITHUB_OUTPUT | |
| echo "CLIENT_ID=$clientID" >> $GITHUB_OUTPUT | |
| echo "β Client details fetched successfully!" | |
| - name: Fetch and Escape Client Details for multi tenant π | |
| id: fetch_credentials_mt | |
| run: | | |
| echo "Fetching client details for multi tenant..." | |
| service_instance_guid=$(cf service bookshop-mt-uaa --guid) | |
| if [ -z "$service_instance_guid" ]; then | |
| echo "β Error: Unable to retrieve service instance GUID"; exit 1; | |
| fi | |
| bindings_response=$(cf curl "/v3/service_credential_bindings?service_instance_guids=${service_instance_guid}") | |
| binding_guid=$(echo "$bindings_response" | jq -r '.resources[0].guid') | |
| if [ -z "$binding_guid" ]; then | |
| echo "β Error: Unable to retrieve binding GUID"; exit 1; | |
| fi | |
| binding_details=$(cf curl "/v3/service_credential_bindings/${binding_guid}/details") | |
| clientSecret_mt=$(echo "$binding_details" | jq -r '.credentials.clientsecret') | |
| if [ -z "$clientSecret_mt" ] || [ "$clientSecret_mt" == "null" ]; then | |
| echo "β Error: clientSecret_mt is not set or is null"; exit 1; | |
| fi | |
| escapedClientSecret_mt=$(echo "$clientSecret_mt" | sed 's/\$/\\$/g') | |
| echo "::add-mask::$escapedClientSecret_mt" | |
| clientID_mt=$(echo "$binding_details" | jq -r '.credentials.clientid') | |
| if [ -z "$clientID_mt" ] || [ "$clientID_mt" == "null" ]; then | |
| echo "β Error: clientID_mt is not set or is null"; exit 1; | |
| fi | |
| echo "::add-mask::$clientID_mt" | |
| echo "CLIENT_SECRET_MT=$escapedClientSecret_mt" >> $GITHUB_OUTPUT | |
| echo "CLIENT_ID_MT=$clientID_mt" >> $GITHUB_OUTPUT | |
| echo "β Multi-tenant client details fetched successfully!" | |
| - name: Prepare credentials file π | |
| env: | |
| CLIENT_SECRET: ${{ steps.fetch_credentials.outputs.CLIENT_SECRET }} | |
| CLIENT_ID: ${{ steps.fetch_credentials.outputs.CLIENT_ID }} | |
| CLIENT_SECRET_MT: ${{ steps.fetch_credentials_mt.outputs.CLIENT_SECRET_MT }} | |
| CLIENT_ID_MT: ${{ steps.fetch_credentials_mt.outputs.CLIENT_ID_MT }} | |
| CMIS_CLIENT_ID: ${{ secrets.CMISCLIENTID }} | |
| CMIS_CLIENT_SECRET: ${{ secrets.CMISCLIENTSECRET }} | |
| run: | | |
| echo "π Preparing credentials for ${{ matrix.tokenFlow }} - ${{ matrix.tenant }}..." | |
| set -e | |
| PROPERTIES_FILE="sdm/src/test/resources/credentials.properties" | |
| appUrl="${{ secrets.CF_ORG }}-${{ steps.determine_space.outputs.space }}-demoappjava-srv.cfapps.eu12.hana.ondemand.com" | |
| appUrlMT="${{ secrets.CF_ORG }}-${{ steps.determine_space.outputs.space }}-bookshop-mt-srv.cfapps.eu12.hana.ondemand.com" | |
| authUrl="${{ secrets.CAPAUTH_URL }}" | |
| authUrlMT1="${{ secrets.AUTHURLMT1 }}" | |
| authUrlMT2="${{ secrets.AUTHURLMT2 }}" | |
| clientID="${{ env.CLIENT_ID }}" | |
| clientSecret="${{ env.CLIENT_SECRET }}" | |
| clientIDMT="${{ env.CLIENT_ID_MT }}" | |
| clientSecretMT="${{ env.CLIENT_SECRET_MT }}" | |
| username="${{ secrets.CF_USER }}" | |
| password="${{ secrets.CF_PASSWORD }}" | |
| noSDMRoleUsername="${{ secrets.NOSDMROLEUSERNAME }}" | |
| noSDMRoleUserPassword="${{ secrets.NOSDMROLEUSERPASSWORD }}" | |
| CMIS_URL="${{ secrets.CMIS_URL }}" | |
| cmisClientID="$CMIS_CLIENT_ID" | |
| cmisClientSecret="$CMIS_CLIENT_SECRET" | |
| defaultRepositoryID="${{ secrets.DEFAULTREPOSITORYID }}" | |
| defaultRepositoryIDMT="${{ secrets.DEFAULTREPOSITORYIDMT }}" | |
| echo "::add-mask::$clientSecret" | |
| echo "::add-mask::$clientID" | |
| echo "::add-mask::$clientSecretMT" | |
| echo "::add-mask::$clientIDMT" | |
| echo "::add-mask::$username" | |
| echo "::add-mask::$password" | |
| echo "::add-mask::$noSDMRoleUsername" | |
| echo "::add-mask::$noSDMRoleUserPassword" | |
| echo "::add-mask::$CMIS_URL" | |
| echo "::add-mask::$cmisClientID" | |
| echo "::add-mask::$cmisClientSecret" | |
| if [ -z "$appUrl" ]; then echo "β Error: appUrl is not set"; exit 1; fi | |
| if [ -z "$appUrlMT" ]; then echo "β Error: appUrlMT is not set"; exit 1; fi | |
| if [ -z "$authUrl" ]; then echo "β Error: authUrl is not set"; exit 1; fi | |
| if [ -z "$authUrlMT1" ]; then echo "β Error: authUrlMT1 is not set"; exit 1; fi | |
| if [ -z "$authUrlMT2" ]; then echo "β Error: authUrlMT2 is not set"; exit 1; fi | |
| if [ -z "$clientID" ]; then echo "β Error: clientID is not set"; exit 1; fi | |
| if [ -z "$clientSecret" ]; then echo "β Error: clientSecret is not set"; exit 1; fi | |
| if [ -z "$clientIDMT" ]; then echo "β Error: clientIDMT is not set"; exit 1; fi | |
| if [ -z "$clientSecretMT" ]; then echo "β Error: clientSecretMT is not set"; exit 1; fi | |
| if [ -z "$username" ]; then echo "β Error: username is not set"; exit 1; fi | |
| if [ -z "$password" ]; then echo "β Error: password is not set"; exit 1; fi | |
| if [ -z "$noSDMRoleUsername" ]; then echo "β Error: noSDMRoleUsername is not set"; exit 1; fi | |
| if [ -z "$noSDMRoleUserPassword" ]; then echo "β Error: noSDMRoleUserPassword is not set"; exit 1; fi | |
| if [ -z "$CMIS_URL" ]; then echo "β Error: CMIS_URL is not set"; exit 1; fi | |
| if [ -z "$cmisClientID" ]; then echo "β Error: cmisClientID is not set"; exit 1; fi | |
| if [ -z "$cmisClientSecret" ]; then echo "β Error: cmisClientSecret is not set"; exit 1; fi | |
| cat > "$PROPERTIES_FILE" <<EOL | |
| appUrl=$appUrl | |
| appUrlMT=$appUrlMT | |
| authUrl=$authUrl | |
| authUrlMT1=$authUrlMT1 | |
| authUrlMT2=$authUrlMT2 | |
| clientID=$clientID | |
| clientSecret=$clientSecret | |
| clientIDMT=$clientIDMT | |
| clientSecretMT=$clientSecretMT | |
| username=$username | |
| password=$password | |
| noSDMRoleUsername=$noSDMRoleUsername | |
| noSDMRoleUserPassword=$noSDMRoleUserPassword | |
| CMIS_URL=$CMIS_URL | |
| cmisClientID=$cmisClientID | |
| cmisClientSecret=$cmisClientSecret | |
| defaultRepositoryID=$defaultRepositoryID | |
| defaultRepositoryIDMT=$defaultRepositoryIDMT | |
| EOL | |
| echo "β Credentials file prepared!" | |
| - name: Download virus test file π₯ | |
| run: | | |
| curl -fSL "http://www.eicar.org/download/eicar.com.txt" -o "sdm/eicar.com.txt" | |
| sleep 5 | |
| if [ -f "sdm/eicar.com.txt" ]; then | |
| FILE_SIZE=$(stat -c '%s' "sdm/eicar.com.txt") | |
| echo "File exists β Size: $FILE_SIZE bytes" | |
| else | |
| echo "β File NOT found at path: sdm/eicar.com.txt" | |
| exit 1 | |
| fi | |
| - name: Run integration tests (${{ matrix.testClass }} - ${{ matrix.tokenFlow }} - ${{ matrix.tenant }}) π― | |
| run: | | |
| echo "π― Running Maven integration tests: testClass=${{ matrix.testClass }}, tokenFlow=${{ matrix.tokenFlow }}, tenant=${{ matrix.tenant }}" | |
| mvn clean verify -P integration-tests -DtokenFlow=${{ matrix.tokenFlow }} -DtenancyModel=multi -Dtenant=${{ matrix.tenant }} -DskipUnitTests -Deicar.file.path=eicar.com.txt -Dfailsafe.includes="**/${{ matrix.testClass }}.java" | |
| echo "β Integration tests completed for ${{ matrix.testClass }} - ${{ matrix.tokenFlow }} - ${{ matrix.tenant }}!" | |
| - name: Upload test results π | |
| if: "!cancelled()" | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-${{ matrix.testClass }}-${{ matrix.tokenFlow }}-${{ matrix.tenant }} | |
| path: | | |
| sdm/target/surefire-reports/ | |
| sdm/target/failsafe-reports/ | |
| retention-days: 7 | |
| # Versioned tests run in parallel; first entry to start switches repo, others skip restage | |
| versioned-test: | |
| runs-on: ubuntu-latest | |
| needs: integration-test | |
| if: "!cancelled()" | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| tokenFlow: [namedUser, technicalUser] | |
| tenant: [TENANT1, TENANT2] | |
| testClass: | |
| - IntegrationTest_SingleFacet_VersionedRepository | |
| - IntegrationTest_MultipleFacet_VersionedRepository | |
| - IntegrationTest_Chapters_MultipleFacet_VersionedRepository | |
| steps: | |
| - name: Checkout repository π | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.event.inputs.branch_name }} | |
| - name: Set up Java 17 β | |
| uses: actions/setup-java@v3 | |
| with: | |
| java-version: 17 | |
| distribution: 'temurin' | |
| cache: 'maven' | |
| - name: Cache CF CLI π¦ | |
| id: cache-cf-cli | |
| uses: actions/cache@v4 | |
| with: | |
| path: /usr/bin/cf8 | |
| key: cf-cli-v8-${{ runner.os }} | |
| - name: Install Cloud Foundry CLI π§ | |
| if: steps.cache-cf-cli.outputs.cache-hit != 'true' | |
| run: | | |
| wget -q -O - https://packages.cloudfoundry.org/debian/cli.cloudfoundry.org.key | sudo apt-key add - | |
| echo "deb https://packages.cloudfoundry.org/debian stable main" | sudo tee /etc/apt/sources.list.d/cloudfoundry-cli.list | |
| sudo apt-get update | |
| sudo apt-get install cf8-cli | |
| - name: Install jq π¦ | |
| run: | | |
| if ! command -v jq &> /dev/null; then | |
| sudo apt-get update && sudo apt-get install -y jq | |
| fi | |
| - name: Determine Cloud Foundry Space π | |
| id: determine_space | |
| run: | | |
| if [ "${{ github.event.inputs.cf_space }}" == "developcap" ]; then | |
| space="${{ secrets.CF_SPACE }}" | |
| else | |
| space="${{ github.event.inputs.cf_space }}" | |
| fi | |
| echo "space=$space" >> $GITHUB_OUTPUT | |
| - name: Login to Cloud Foundry π | |
| run: | | |
| cf login -a ${{ secrets.CF_API }} \ | |
| -u ${{ secrets.CF_USER }} \ | |
| -p ${{ secrets.CF_PASSWORD }} \ | |
| -o ${{ secrets.CF_ORG }} \ | |
| -s ${{ steps.determine_space.outputs.space }} | |
| - name: Ensure versioned repository is active π | |
| run: | | |
| APP_GUID=$(cf app bookshop-mt-srv --guid) | |
| CURRENT=$(cf curl "/v3/apps/${APP_GUID}/environment_variables" | jq -r '.var.REPOSITORY_ID // empty') | |
| if [ "$CURRENT" != "${{ secrets.VERSIONEDREPOSITORYID }}" ]; then | |
| echo "π Switching REPOSITORY_ID to versioned repository..." | |
| cf set-env bookshop-mt-srv REPOSITORY_ID "${{ secrets.VERSIONEDREPOSITORYID }}" | |
| echo "π Restaging application..." | |
| cf restage bookshop-mt-srv > /dev/null 2>&1 | |
| echo "β Switched to versioned repository!" | |
| else | |
| echo "β Repository already set to versioned, skipping restage" | |
| fi | |
| - name: Fetch and Escape Client Details for single tenant π | |
| id: fetch_credentials | |
| run: | | |
| service_instance_guid=$(cf service demoappjava-public-uaa --guid) | |
| if [ -z "$service_instance_guid" ]; then | |
| echo "β Error: Unable to retrieve service instance GUID"; exit 1; | |
| fi | |
| bindings_response=$(cf curl "/v3/service_credential_bindings?service_instance_guids=${service_instance_guid}") | |
| binding_guid=$(echo "$bindings_response" | jq -r '.resources[0].guid') | |
| if [ -z "$binding_guid" ]; then | |
| echo "β Error: Unable to retrieve binding GUID"; exit 1; | |
| fi | |
| binding_details=$(cf curl "/v3/service_credential_bindings/${binding_guid}/details") | |
| clientSecret=$(echo "$binding_details" | jq -r '.credentials.clientsecret') | |
| if [ -z "$clientSecret" ] || [ "$clientSecret" == "null" ]; then | |
| echo "β Error: clientSecret is not set or is null"; exit 1; | |
| fi | |
| escapedClientSecret=$(echo "$clientSecret" | sed 's/\$/\\$/g') | |
| echo "::add-mask::$escapedClientSecret" | |
| clientID=$(echo "$binding_details" | jq -r '.credentials.clientid') | |
| if [ -z "$clientID" ] || [ "$clientID" == "null" ]; then | |
| echo "β Error: clientID is not set or is null"; exit 1; | |
| fi | |
| echo "::add-mask::$clientID" | |
| echo "CLIENT_SECRET=$escapedClientSecret" >> $GITHUB_OUTPUT | |
| echo "CLIENT_ID=$clientID" >> $GITHUB_OUTPUT | |
| - name: Fetch and Escape Client Details for multi tenant π | |
| id: fetch_credentials_mt | |
| run: | | |
| service_instance_guid=$(cf service bookshop-mt-uaa --guid) | |
| if [ -z "$service_instance_guid" ]; then | |
| echo "β Error: Unable to retrieve service instance GUID"; exit 1; | |
| fi | |
| bindings_response=$(cf curl "/v3/service_credential_bindings?service_instance_guids=${service_instance_guid}") | |
| binding_guid=$(echo "$bindings_response" | jq -r '.resources[0].guid') | |
| if [ -z "$binding_guid" ]; then | |
| echo "β Error: Unable to retrieve binding GUID"; exit 1; | |
| fi | |
| binding_details=$(cf curl "/v3/service_credential_bindings/${binding_guid}/details") | |
| clientSecret_mt=$(echo "$binding_details" | jq -r '.credentials.clientsecret') | |
| if [ -z "$clientSecret_mt" ] || [ "$clientSecret_mt" == "null" ]; then | |
| echo "β Error: clientSecret_mt is not set or is null"; exit 1; | |
| fi | |
| escapedClientSecret_mt=$(echo "$clientSecret_mt" | sed 's/\$/\\$/g') | |
| echo "::add-mask::$escapedClientSecret_mt" | |
| clientID_mt=$(echo "$binding_details" | jq -r '.credentials.clientid') | |
| if [ -z "$clientID_mt" ] || [ "$clientID_mt" == "null" ]; then | |
| echo "β Error: clientID_mt is not set or is null"; exit 1; | |
| fi | |
| echo "::add-mask::$clientID_mt" | |
| echo "CLIENT_SECRET_MT=$escapedClientSecret_mt" >> $GITHUB_OUTPUT | |
| echo "CLIENT_ID_MT=$clientID_mt" >> $GITHUB_OUTPUT | |
| - name: Run versioned integration tests π― (${{ matrix.testClass }} - ${{ matrix.tokenFlow }} - ${{ matrix.tenant }}) | |
| env: | |
| CLIENT_SECRET: ${{ steps.fetch_credentials.outputs.CLIENT_SECRET }} | |
| CLIENT_ID: ${{ steps.fetch_credentials.outputs.CLIENT_ID }} | |
| CLIENT_SECRET_MT: ${{ steps.fetch_credentials_mt.outputs.CLIENT_SECRET_MT }} | |
| CLIENT_ID_MT: ${{ steps.fetch_credentials_mt.outputs.CLIENT_ID_MT }} | |
| CMIS_CLIENT_ID: ${{ secrets.CMISCLIENTID }} | |
| CMIS_CLIENT_SECRET: ${{ secrets.CMISCLIENTSECRET }} | |
| run: | | |
| set -e | |
| PROPERTIES_FILE="sdm/src/test/resources/credentials.properties" | |
| appUrl="${{ secrets.CF_ORG }}-${{ steps.determine_space.outputs.space }}-demoappjava-srv.cfapps.eu12.hana.ondemand.com" | |
| appUrlMT="${{ secrets.CF_ORG }}-${{ steps.determine_space.outputs.space }}-bookshop-mt-srv.cfapps.eu12.hana.ondemand.com" | |
| authUrl="${{ secrets.CAPAUTH_URL }}" | |
| authUrlMT1="${{ secrets.AUTHURLMT1 }}" | |
| authUrlMT2="${{ secrets.AUTHURLMT2 }}" | |
| clientID="${{ env.CLIENT_ID }}" | |
| clientSecret="${{ env.CLIENT_SECRET }}" | |
| clientIDMT="${{ env.CLIENT_ID_MT }}" | |
| clientSecretMT="${{ env.CLIENT_SECRET_MT }}" | |
| username="${{ secrets.CF_USER }}" | |
| password="${{ secrets.CF_PASSWORD }}" | |
| noSDMRoleUsername="${{ secrets.NOSDMROLEUSERNAME }}" | |
| noSDMRoleUserPassword="${{ secrets.NOSDMROLEUSERPASSWORD }}" | |
| versionedRepositoryID="${{ secrets.VERSIONEDREPOSITORYID }}" | |
| virusScanRepositoryID="${{ secrets.VIRUSSCANREPOSITORYID }}" | |
| defaultRepositoryID="${{ secrets.DEFAULTREPOSITORYID }}" | |
| defaultRepositoryIDMT="${{ secrets.DEFAULTREPOSITORYIDMT }}" | |
| CMIS_URL="${{ secrets.CMIS_URL }}" | |
| cmisClientID="$CMIS_CLIENT_ID" | |
| cmisClientSecret="$CMIS_CLIENT_SECRET" | |
| cat > "$PROPERTIES_FILE" <<EOL | |
| appUrl=$appUrl | |
| appUrlMT=$appUrlMT | |
| authUrl=$authUrl | |
| authUrlMT1=$authUrlMT1 | |
| authUrlMT2=$authUrlMT2 | |
| clientID=$clientID | |
| clientSecret=$clientSecret | |
| clientIDMT=$clientIDMT | |
| clientSecretMT=$clientSecretMT | |
| username=$username | |
| password=$password | |
| noSDMRoleUsername=$noSDMRoleUsername | |
| noSDMRoleUserPassword=$noSDMRoleUserPassword | |
| versionedRepositoryID=$versionedRepositoryID | |
| virusScanRepositoryID=$virusScanRepositoryID | |
| defaultRepositoryID=$defaultRepositoryID | |
| defaultRepositoryIDMT=$defaultRepositoryIDMT | |
| CMIS_URL=$CMIS_URL | |
| cmisClientID=$cmisClientID | |
| cmisClientSecret=$cmisClientSecret | |
| EOL | |
| echo "π― Running versioned integration tests for ${{ matrix.testClass }} - ${{ matrix.tokenFlow }} - ${{ matrix.tenant }}..." | |
| mvn clean verify -P integration-tests \ | |
| -DtokenFlow=${{ matrix.tokenFlow }} -DtenancyModel=multi -Dtenant=${{ matrix.tenant }} \ | |
| -DskipUnitTests -Dfailsafe.includes="**/${{ matrix.testClass }}.java" | |
| # Virus scan tests run in parallel; first entry to start switches repo, others skip restage | |
| virusscan-test: | |
| runs-on: ubuntu-latest | |
| needs: versioned-test | |
| if: "!cancelled()" | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| tokenFlow: [namedUser, technicalUser] | |
| tenant: [TENANT1, TENANT2] | |
| testClass: | |
| - IntegrationTest_SingleFacet_Virus | |
| - IntegrationTest_MultipleFacet_Virus | |
| - IntegrationTest_Chapters_MultipleFacet_Virus | |
| steps: | |
| - name: Checkout repository π | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.event.inputs.branch_name }} | |
| - name: Set up Java 17 β | |
| uses: actions/setup-java@v3 | |
| with: | |
| java-version: 17 | |
| distribution: 'temurin' | |
| cache: 'maven' | |
| - name: Cache CF CLI π¦ | |
| id: cache-cf-cli | |
| uses: actions/cache@v4 | |
| with: | |
| path: /usr/bin/cf8 | |
| key: cf-cli-v8-${{ runner.os }} | |
| - name: Install Cloud Foundry CLI π§ | |
| if: steps.cache-cf-cli.outputs.cache-hit != 'true' | |
| run: | | |
| wget -q -O - https://packages.cloudfoundry.org/debian/cli.cloudfoundry.org.key | sudo apt-key add - | |
| echo "deb https://packages.cloudfoundry.org/debian stable main" | sudo tee /etc/apt/sources.list.d/cloudfoundry-cli.list | |
| sudo apt-get update | |
| sudo apt-get install cf8-cli | |
| - name: Install jq π¦ | |
| run: | | |
| if ! command -v jq &> /dev/null; then | |
| sudo apt-get update && sudo apt-get install -y jq | |
| fi | |
| - name: Determine Cloud Foundry Space π | |
| id: determine_space | |
| run: | | |
| if [ "${{ github.event.inputs.cf_space }}" == "developcap" ]; then | |
| space="${{ secrets.CF_SPACE }}" | |
| else | |
| space="${{ github.event.inputs.cf_space }}" | |
| fi | |
| echo "space=$space" >> $GITHUB_OUTPUT | |
| - name: Login to Cloud Foundry π | |
| run: | | |
| cf login -a ${{ secrets.CF_API }} \ | |
| -u ${{ secrets.CF_USER }} \ | |
| -p ${{ secrets.CF_PASSWORD }} \ | |
| -o ${{ secrets.CF_ORG }} \ | |
| -s ${{ steps.determine_space.outputs.space }} | |
| - name: Ensure virus scan repository is active π | |
| run: | | |
| APP_GUID=$(cf app bookshop-mt-srv --guid) | |
| CURRENT=$(cf curl "/v3/apps/${APP_GUID}/environment_variables" | jq -r '.var.REPOSITORY_ID // empty') | |
| if [ "$CURRENT" != "${{ secrets.VIRUSSCANREPOSITORYID }}" ]; then | |
| echo "π Switching REPOSITORY_ID to virus scan repository..." | |
| cf set-env bookshop-mt-srv REPOSITORY_ID "${{ secrets.VIRUSSCANREPOSITORYID }}" | |
| echo "π Restaging application..." | |
| cf restage bookshop-mt-srv > /dev/null 2>&1 | |
| echo "β Switched to virus scan repository!" | |
| else | |
| echo "β Repository already set to virus scan, skipping restage" | |
| fi | |
| - name: Fetch and Escape Client Details for single tenant π | |
| id: fetch_credentials | |
| run: | | |
| service_instance_guid=$(cf service demoappjava-public-uaa --guid) | |
| if [ -z "$service_instance_guid" ]; then | |
| echo "β Error: Unable to retrieve service instance GUID"; exit 1; | |
| fi | |
| bindings_response=$(cf curl "/v3/service_credential_bindings?service_instance_guids=${service_instance_guid}") | |
| binding_guid=$(echo "$bindings_response" | jq -r '.resources[0].guid') | |
| if [ -z "$binding_guid" ]; then | |
| echo "β Error: Unable to retrieve binding GUID"; exit 1; | |
| fi | |
| binding_details=$(cf curl "/v3/service_credential_bindings/${binding_guid}/details") | |
| clientSecret=$(echo "$binding_details" | jq -r '.credentials.clientsecret') | |
| if [ -z "$clientSecret" ] || [ "$clientSecret" == "null" ]; then | |
| echo "β Error: clientSecret is not set or is null"; exit 1; | |
| fi | |
| escapedClientSecret=$(echo "$clientSecret" | sed 's/\$/\\$/g') | |
| echo "::add-mask::$escapedClientSecret" | |
| clientID=$(echo "$binding_details" | jq -r '.credentials.clientid') | |
| if [ -z "$clientID" ] || [ "$clientID" == "null" ]; then | |
| echo "β Error: clientID is not set or is null"; exit 1; | |
| fi | |
| echo "::add-mask::$clientID" | |
| echo "CLIENT_SECRET=$escapedClientSecret" >> $GITHUB_OUTPUT | |
| echo "CLIENT_ID=$clientID" >> $GITHUB_OUTPUT | |
| - name: Fetch and Escape Client Details for multi tenant π | |
| id: fetch_credentials_mt | |
| run: | | |
| service_instance_guid=$(cf service bookshop-mt-uaa --guid) | |
| if [ -z "$service_instance_guid" ]; then | |
| echo "β Error: Unable to retrieve service instance GUID"; exit 1; | |
| fi | |
| bindings_response=$(cf curl "/v3/service_credential_bindings?service_instance_guids=${service_instance_guid}") | |
| binding_guid=$(echo "$bindings_response" | jq -r '.resources[0].guid') | |
| if [ -z "$binding_guid" ]; then | |
| echo "β Error: Unable to retrieve binding GUID"; exit 1; | |
| fi | |
| binding_details=$(cf curl "/v3/service_credential_bindings/${binding_guid}/details") | |
| clientSecret_mt=$(echo "$binding_details" | jq -r '.credentials.clientsecret') | |
| if [ -z "$clientSecret_mt" ] || [ "$clientSecret_mt" == "null" ]; then | |
| echo "β Error: clientSecret_mt is not set or is null"; exit 1; | |
| fi | |
| escapedClientSecret_mt=$(echo "$clientSecret_mt" | sed 's/\$/\\$/g') | |
| echo "::add-mask::$escapedClientSecret_mt" | |
| clientID_mt=$(echo "$binding_details" | jq -r '.credentials.clientid') | |
| if [ -z "$clientID_mt" ] || [ "$clientID_mt" == "null" ]; then | |
| echo "β Error: clientID_mt is not set or is null"; exit 1; | |
| fi | |
| echo "::add-mask::$clientID_mt" | |
| echo "CLIENT_SECRET_MT=$escapedClientSecret_mt" >> $GITHUB_OUTPUT | |
| echo "CLIENT_ID_MT=$clientID_mt" >> $GITHUB_OUTPUT | |
| - name: Download virus test file π₯ | |
| run: | | |
| curl -fSL "http://www.eicar.org/download/eicar.com.txt" -o "sdm/eicar.com.txt" | |
| sleep 5 | |
| if [ -f "sdm/eicar.com.txt" ]; then | |
| FILE_SIZE=$(stat -c '%s' "sdm/eicar.com.txt") | |
| echo "File exists β Size: $FILE_SIZE bytes" | |
| else | |
| echo "β File NOT found at path: sdm/eicar.com.txt" | |
| exit 1 | |
| fi | |
| - name: Run virus scan integration tests π― (${{ matrix.testClass }} - ${{ matrix.tokenFlow }} - ${{ matrix.tenant }}) | |
| env: | |
| CLIENT_SECRET: ${{ steps.fetch_credentials.outputs.CLIENT_SECRET }} | |
| CLIENT_ID: ${{ steps.fetch_credentials.outputs.CLIENT_ID }} | |
| CLIENT_SECRET_MT: ${{ steps.fetch_credentials_mt.outputs.CLIENT_SECRET_MT }} | |
| CLIENT_ID_MT: ${{ steps.fetch_credentials_mt.outputs.CLIENT_ID_MT }} | |
| CMIS_CLIENT_ID: ${{ secrets.CMISCLIENTID }} | |
| CMIS_CLIENT_SECRET: ${{ secrets.CMISCLIENTSECRET }} | |
| run: | | |
| set -e | |
| PROPERTIES_FILE="sdm/src/test/resources/credentials.properties" | |
| appUrl="${{ secrets.CF_ORG }}-${{ steps.determine_space.outputs.space }}-demoappjava-srv.cfapps.eu12.hana.ondemand.com" | |
| appUrlMT="${{ secrets.CF_ORG }}-${{ steps.determine_space.outputs.space }}-bookshop-mt-srv.cfapps.eu12.hana.ondemand.com" | |
| authUrl="${{ secrets.CAPAUTH_URL }}" | |
| authUrlMT1="${{ secrets.AUTHURLMT1 }}" | |
| authUrlMT2="${{ secrets.AUTHURLMT2 }}" | |
| clientID="${{ env.CLIENT_ID }}" | |
| clientSecret="${{ env.CLIENT_SECRET }}" | |
| clientIDMT="${{ env.CLIENT_ID_MT }}" | |
| clientSecretMT="${{ env.CLIENT_SECRET_MT }}" | |
| username="${{ secrets.CF_USER }}" | |
| password="${{ secrets.CF_PASSWORD }}" | |
| noSDMRoleUsername="${{ secrets.NOSDMROLEUSERNAME }}" | |
| noSDMRoleUserPassword="${{ secrets.NOSDMROLEUSERPASSWORD }}" | |
| versionedRepositoryID="${{ secrets.VERSIONEDREPOSITORYID }}" | |
| virusScanRepositoryID="${{ secrets.VIRUSSCANREPOSITORYID }}" | |
| defaultRepositoryID="${{ secrets.DEFAULTREPOSITORYID }}" | |
| defaultRepositoryIDMT="${{ secrets.DEFAULTREPOSITORYIDMT }}" | |
| CMIS_URL="${{ secrets.CMIS_URL }}" | |
| cmisClientID="$CMIS_CLIENT_ID" | |
| cmisClientSecret="$CMIS_CLIENT_SECRET" | |
| cat > "$PROPERTIES_FILE" <<EOL | |
| appUrl=$appUrl | |
| appUrlMT=$appUrlMT | |
| authUrl=$authUrl | |
| authUrlMT1=$authUrlMT1 | |
| authUrlMT2=$authUrlMT2 | |
| clientID=$clientID | |
| clientSecret=$clientSecret | |
| clientIDMT=$clientIDMT | |
| clientSecretMT=$clientSecretMT | |
| username=$username | |
| password=$password | |
| noSDMRoleUsername=$noSDMRoleUsername | |
| noSDMRoleUserPassword=$noSDMRoleUserPassword | |
| versionedRepositoryID=$versionedRepositoryID | |
| virusScanRepositoryID=$virusScanRepositoryID | |
| defaultRepositoryID=$defaultRepositoryID | |
| defaultRepositoryIDMT=$defaultRepositoryIDMT | |
| CMIS_URL=$CMIS_URL | |
| cmisClientID=$cmisClientID | |
| cmisClientSecret=$cmisClientSecret | |
| EOL | |
| echo "π― Running virus scan integration tests for ${{ matrix.testClass }} - ${{ matrix.tokenFlow }} - ${{ matrix.tenant }}..." | |
| mvn clean verify -P integration-tests \ | |
| -DtokenFlow=${{ matrix.tokenFlow }} -DtenancyModel=multi -Dtenant=${{ matrix.tenant }} \ | |
| -DskipUnitTests -Deicar.file.path=eicar.com.txt \ | |
| -Dfailsafe.includes="**/${{ matrix.testClass }}.java" | |
| # Revert repository to default after virus scan tests (always runs) | |
| virusscan-cleanup: | |
| runs-on: ubuntu-latest | |
| needs: virusscan-test | |
| if: always() | |
| steps: | |
| - name: Cache CF CLI π¦ | |
| id: cache-cf-cli | |
| uses: actions/cache@v4 | |
| with: | |
| path: /usr/bin/cf8 | |
| key: cf-cli-v8-${{ runner.os }} | |
| - name: Install Cloud Foundry CLI π§ | |
| if: steps.cache-cf-cli.outputs.cache-hit != 'true' | |
| run: | | |
| wget -q -O - https://packages.cloudfoundry.org/debian/cli.cloudfoundry.org.key | sudo apt-key add - | |
| echo "deb https://packages.cloudfoundry.org/debian stable main" | sudo tee /etc/apt/sources.list.d/cloudfoundry-cli.list | |
| sudo apt-get update | |
| sudo apt-get install cf8-cli | |
| - name: Install jq π¦ | |
| run: | | |
| if ! command -v jq &> /dev/null; then | |
| sudo apt-get update && sudo apt-get install -y jq | |
| fi | |
| - name: Determine Cloud Foundry Space π | |
| id: determine_space | |
| run: | | |
| if [ "${{ github.event.inputs.cf_space }}" == "developcap" ]; then | |
| space="${{ secrets.CF_SPACE }}" | |
| else | |
| space="${{ github.event.inputs.cf_space }}" | |
| fi | |
| echo "space=$space" >> $GITHUB_OUTPUT | |
| - name: Login to Cloud Foundry π | |
| run: | | |
| cf login -a ${{ secrets.CF_API }} \ | |
| -u ${{ secrets.CF_USER }} \ | |
| -p ${{ secrets.CF_PASSWORD }} \ | |
| -o ${{ secrets.CF_ORG }} \ | |
| -s ${{ steps.determine_space.outputs.space }} | |
| - name: Revert to Default Repository π | |
| run: | | |
| echo "π Reverting REPOSITORY_ID to default repository..." | |
| cf set-env bookshop-mt-srv REPOSITORY_ID "${{ secrets.DEFAULTREPOSITORYIDMT }}" | |
| echo "π Restaging application..." | |
| cf restage bookshop-mt-srv > /dev/null 2>&1 | |
| echo "β Reverted to default repository!" | |
| # Repo-specific tests run one at a time (max-parallel: 1) so each shows individually in UI | |
| repospecific-test: | |
| runs-on: ubuntu-latest | |
| needs: virusscan-cleanup | |
| if: "!cancelled()" | |
| strategy: | |
| fail-fast: false | |
| max-parallel: 1 | |
| matrix: | |
| tokenFlow: [namedUser, technicalUser] | |
| tenant: [TENANT1, TENANT2] | |
| testClass: | |
| - IntegrationTest_SingleFacet_RepoSpecific | |
| - IntegrationTest_MultipleFacet_RepoSpecific | |
| - IntegrationTest_Chapters_MultipleFacet_RepoSpecific | |
| steps: | |
| - name: Checkout repository π | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.event.inputs.branch_name }} | |
| - name: Set up Java 17 β | |
| uses: actions/setup-java@v3 | |
| with: | |
| java-version: 17 | |
| distribution: 'temurin' | |
| cache: 'maven' | |
| - name: Cache CF CLI π¦ | |
| id: cache-cf-cli | |
| uses: actions/cache@v4 | |
| with: | |
| path: /usr/bin/cf8 | |
| key: cf-cli-v8-${{ runner.os }} | |
| - name: Install Cloud Foundry CLI π§ | |
| if: steps.cache-cf-cli.outputs.cache-hit != 'true' | |
| run: | | |
| wget -q -O - https://packages.cloudfoundry.org/debian/cli.cloudfoundry.org.key | sudo apt-key add - | |
| echo "deb https://packages.cloudfoundry.org/debian stable main" | sudo tee /etc/apt/sources.list.d/cloudfoundry-cli.list | |
| sudo apt-get update | |
| sudo apt-get install cf8-cli | |
| - name: Install jq π¦ | |
| run: | | |
| if ! command -v jq &> /dev/null; then | |
| sudo apt-get update && sudo apt-get install -y jq | |
| fi | |
| - name: Determine Cloud Foundry Space π | |
| id: determine_space | |
| run: | | |
| if [ "${{ github.event.inputs.cf_space }}" == "developcap" ]; then | |
| space="${{ secrets.CF_SPACE }}" | |
| else | |
| space="${{ github.event.inputs.cf_space }}" | |
| fi | |
| echo "space=$space" >> $GITHUB_OUTPUT | |
| - name: Login to Cloud Foundry π | |
| run: | | |
| cf login -a ${{ secrets.CF_API }} \ | |
| -u ${{ secrets.CF_USER }} \ | |
| -p ${{ secrets.CF_PASSWORD }} \ | |
| -o ${{ secrets.CF_ORG }} \ | |
| -s ${{ steps.determine_space.outputs.space }} | |
| - name: Fetch and Escape Client Details for single tenant π | |
| id: fetch_credentials | |
| run: | | |
| service_instance_guid=$(cf service demoappjava-public-uaa --guid) | |
| if [ -z "$service_instance_guid" ]; then | |
| echo "β Error: Unable to retrieve service instance GUID"; exit 1; | |
| fi | |
| bindings_response=$(cf curl "/v3/service_credential_bindings?service_instance_guids=${service_instance_guid}") | |
| binding_guid=$(echo "$bindings_response" | jq -r '.resources[0].guid') | |
| if [ -z "$binding_guid" ]; then | |
| echo "β Error: Unable to retrieve binding GUID"; exit 1; | |
| fi | |
| binding_details=$(cf curl "/v3/service_credential_bindings/${binding_guid}/details") | |
| clientSecret=$(echo "$binding_details" | jq -r '.credentials.clientsecret') | |
| if [ -z "$clientSecret" ] || [ "$clientSecret" == "null" ]; then | |
| echo "β Error: clientSecret is not set or is null"; exit 1; | |
| fi | |
| escapedClientSecret=$(echo "$clientSecret" | sed 's/\$/\\$/g') | |
| echo "::add-mask::$escapedClientSecret" | |
| clientID=$(echo "$binding_details" | jq -r '.credentials.clientid') | |
| if [ -z "$clientID" ] || [ "$clientID" == "null" ]; then | |
| echo "β Error: clientID is not set or is null"; exit 1; | |
| fi | |
| echo "::add-mask::$clientID" | |
| echo "CLIENT_SECRET=$escapedClientSecret" >> $GITHUB_OUTPUT | |
| echo "CLIENT_ID=$clientID" >> $GITHUB_OUTPUT | |
| - name: Fetch and Escape Client Details for multi tenant π | |
| id: fetch_credentials_mt | |
| run: | | |
| service_instance_guid=$(cf service bookshop-mt-uaa --guid) | |
| if [ -z "$service_instance_guid" ]; then | |
| echo "β Error: Unable to retrieve service instance GUID"; exit 1; | |
| fi | |
| bindings_response=$(cf curl "/v3/service_credential_bindings?service_instance_guids=${service_instance_guid}") | |
| binding_guid=$(echo "$bindings_response" | jq -r '.resources[0].guid') | |
| if [ -z "$binding_guid" ]; then | |
| echo "β Error: Unable to retrieve binding GUID"; exit 1; | |
| fi | |
| binding_details=$(cf curl "/v3/service_credential_bindings/${binding_guid}/details") | |
| clientSecret_mt=$(echo "$binding_details" | jq -r '.credentials.clientsecret') | |
| if [ -z "$clientSecret_mt" ] || [ "$clientSecret_mt" == "null" ]; then | |
| echo "β Error: clientSecret_mt is not set or is null"; exit 1; | |
| fi | |
| escapedClientSecret_mt=$(echo "$clientSecret_mt" | sed 's/\$/\\$/g') | |
| echo "::add-mask::$escapedClientSecret_mt" | |
| clientID_mt=$(echo "$binding_details" | jq -r '.credentials.clientid') | |
| if [ -z "$clientID_mt" ] || [ "$clientID_mt" == "null" ]; then | |
| echo "β Error: clientID_mt is not set or is null"; exit 1; | |
| fi | |
| echo "::add-mask::$clientID_mt" | |
| echo "CLIENT_SECRET_MT=$escapedClientSecret_mt" >> $GITHUB_OUTPUT | |
| echo "CLIENT_ID_MT=$clientID_mt" >> $GITHUB_OUTPUT | |
| - name: Run repo-specific integration tests π― (${{ matrix.testClass }} - ${{ matrix.tokenFlow }} - ${{ matrix.tenant }}) | |
| env: | |
| CLIENT_SECRET: ${{ steps.fetch_credentials.outputs.CLIENT_SECRET }} | |
| CLIENT_ID: ${{ steps.fetch_credentials.outputs.CLIENT_ID }} | |
| CLIENT_SECRET_MT: ${{ steps.fetch_credentials_mt.outputs.CLIENT_SECRET_MT }} | |
| CLIENT_ID_MT: ${{ steps.fetch_credentials_mt.outputs.CLIENT_ID_MT }} | |
| CMIS_CLIENT_ID: ${{ secrets.CMISCLIENTID }} | |
| CMIS_CLIENT_SECRET: ${{ secrets.CMISCLIENTSECRET }} | |
| run: | | |
| set -e | |
| PROPERTIES_FILE="sdm/src/test/resources/credentials.properties" | |
| appUrl="${{ secrets.CF_ORG }}-${{ steps.determine_space.outputs.space }}-demoappjava-srv.cfapps.eu12.hana.ondemand.com" | |
| appUrlMT="${{ secrets.CF_ORG }}-${{ steps.determine_space.outputs.space }}-bookshop-mt-srv.cfapps.eu12.hana.ondemand.com" | |
| authUrl="${{ secrets.CAPAUTH_URL }}" | |
| authUrlMT1="${{ secrets.AUTHURLMT1 }}" | |
| authUrlMT2="${{ secrets.AUTHURLMT2 }}" | |
| clientID="${{ env.CLIENT_ID }}" | |
| clientSecret="${{ env.CLIENT_SECRET }}" | |
| clientIDMT="${{ env.CLIENT_ID_MT }}" | |
| clientSecretMT="${{ env.CLIENT_SECRET_MT }}" | |
| username="${{ secrets.CF_USER }}" | |
| password="${{ secrets.CF_PASSWORD }}" | |
| noSDMRoleUsername="${{ secrets.NOSDMROLEUSERNAME }}" | |
| noSDMRoleUserPassword="${{ secrets.NOSDMROLEUSERPASSWORD }}" | |
| versionedRepositoryID="${{ secrets.VERSIONEDREPOSITORYID }}" | |
| virusScanRepositoryID="${{ secrets.VIRUSSCANREPOSITORYID }}" | |
| defaultRepositoryID="${{ secrets.DEFAULTREPOSITORYID }}" | |
| defaultRepositoryIDMT="${{ secrets.DEFAULTREPOSITORYIDMT }}" | |
| CMIS_URL="${{ secrets.CMIS_URL }}" | |
| cmisClientID="$CMIS_CLIENT_ID" | |
| cmisClientSecret="$CMIS_CLIENT_SECRET" | |
| cat > "$PROPERTIES_FILE" <<EOL | |
| appUrl=$appUrl | |
| appUrlMT=$appUrlMT | |
| authUrl=$authUrl | |
| authUrlMT1=$authUrlMT1 | |
| authUrlMT2=$authUrlMT2 | |
| clientID=$clientID | |
| clientSecret=$clientSecret | |
| clientIDMT=$clientIDMT | |
| clientSecretMT=$clientSecretMT | |
| username=$username | |
| password=$password | |
| noSDMRoleUsername=$noSDMRoleUsername | |
| noSDMRoleUserPassword=$noSDMRoleUserPassword | |
| versionedRepositoryID=$versionedRepositoryID | |
| virusScanRepositoryID=$virusScanRepositoryID | |
| defaultRepositoryID=$defaultRepositoryID | |
| defaultRepositoryIDMT=$defaultRepositoryIDMT | |
| CMIS_URL=$CMIS_URL | |
| cmisClientID=$cmisClientID | |
| cmisClientSecret=$cmisClientSecret | |
| EOL | |
| echo "π― Running repo-specific integration tests for ${{ matrix.testClass }} - ${{ matrix.tokenFlow }} - ${{ matrix.tenant }}..." | |
| mvn clean verify -P integration-tests \ | |
| -DtokenFlow=${{ matrix.tokenFlow }} -DtenancyModel=multi -Dtenant=${{ matrix.tenant }} \ | |
| -DskipUnitTests -Dfailsafe.includes="**/${{ matrix.testClass }}.java" | |
| # Single self-contained job: run subscription tests for both tenants | |
| # Must run AFTER repospecific-test because subscription tests unsubscribe tenants | |
| subscription-test: | |
| runs-on: ubuntu-latest | |
| needs: repospecific-test | |
| if: "!cancelled()" | |
| steps: | |
| - name: Checkout repository π | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.event.inputs.branch_name }} | |
| - name: Set up Java 17 β | |
| uses: actions/setup-java@v3 | |
| with: | |
| java-version: 17 | |
| distribution: 'temurin' | |
| cache: 'maven' | |
| - name: Cache CF CLI π¦ | |
| id: cache-cf-cli | |
| uses: actions/cache@v4 | |
| with: | |
| path: /usr/bin/cf8 | |
| key: cf-cli-v8-${{ runner.os }} | |
| - name: Install Cloud Foundry CLI π§ | |
| if: steps.cache-cf-cli.outputs.cache-hit != 'true' | |
| run: | | |
| wget -q -O - https://packages.cloudfoundry.org/debian/cli.cloudfoundry.org.key | sudo apt-key add - | |
| echo "deb https://packages.cloudfoundry.org/debian stable main" | sudo tee /etc/apt/sources.list.d/cloudfoundry-cli.list | |
| sudo apt-get update | |
| sudo apt-get install cf8-cli | |
| - name: Install jq π¦ | |
| run: | | |
| if ! command -v jq &> /dev/null; then | |
| sudo apt-get update && sudo apt-get install -y jq | |
| fi | |
| - name: Install BTP CLI π§ | |
| run: | | |
| echo "π Installing SAP BTP CLI..." | |
| curl -fsSL https://cli.btp.cloud.sap/btpcli-install.sh | bash | |
| BTP_BIN=$(find "$HOME/bin" /usr/local/bin -maxdepth 1 -name 'btp' -type f 2>/dev/null | head -1) | |
| if [ -z "$BTP_BIN" ]; then | |
| echo "β btp binary not found after install script." | |
| exit 1 | |
| fi | |
| if [ "$BTP_BIN" != "/usr/local/bin/btp" ]; then | |
| sudo install -m 755 "$BTP_BIN" /usr/local/bin/btp | |
| fi | |
| btp --version | |
| echo "β BTP CLI installed successfully!" | |
| - name: Determine Cloud Foundry Space π | |
| id: determine_space | |
| run: | | |
| if [ "${{ github.event.inputs.cf_space }}" == "developcap" ]; then | |
| space="${{ secrets.CF_SPACE }}" | |
| else | |
| space="${{ github.event.inputs.cf_space }}" | |
| fi | |
| echo "space=$space" >> $GITHUB_OUTPUT | |
| - name: Login to Cloud Foundry π | |
| run: | | |
| cf login -a ${{ secrets.CF_API }} \ | |
| -u ${{ secrets.CF_USER }} \ | |
| -p ${{ secrets.CF_PASSWORD }} \ | |
| -o ${{ secrets.CF_ORG }} \ | |
| -s ${{ steps.determine_space.outputs.space }} | |
| - name: Fetch and Escape Client Details for single tenant π | |
| id: fetch_credentials | |
| run: | | |
| service_instance_guid=$(cf service demoappjava-public-uaa --guid) | |
| if [ -z "$service_instance_guid" ]; then | |
| echo "β Error: Unable to retrieve service instance GUID"; exit 1; | |
| fi | |
| bindings_response=$(cf curl "/v3/service_credential_bindings?service_instance_guids=${service_instance_guid}") | |
| binding_guid=$(echo "$bindings_response" | jq -r '.resources[0].guid') | |
| if [ -z "$binding_guid" ]; then | |
| echo "β Error: Unable to retrieve binding GUID"; exit 1; | |
| fi | |
| binding_details=$(cf curl "/v3/service_credential_bindings/${binding_guid}/details") | |
| clientSecret=$(echo "$binding_details" | jq -r '.credentials.clientsecret') | |
| if [ -z "$clientSecret" ] || [ "$clientSecret" == "null" ]; then | |
| echo "β Error: clientSecret is not set or is null"; exit 1; | |
| fi | |
| escapedClientSecret=$(echo "$clientSecret" | sed 's/\$/\\$/g') | |
| echo "::add-mask::$escapedClientSecret" | |
| clientID=$(echo "$binding_details" | jq -r '.credentials.clientid') | |
| if [ -z "$clientID" ] || [ "$clientID" == "null" ]; then | |
| echo "β Error: clientID is not set or is null"; exit 1; | |
| fi | |
| echo "::add-mask::$clientID" | |
| echo "CLIENT_SECRET=$escapedClientSecret" >> $GITHUB_OUTPUT | |
| echo "CLIENT_ID=$clientID" >> $GITHUB_OUTPUT | |
| - name: Fetch and Escape Client Details for multi tenant π | |
| id: fetch_credentials_mt | |
| run: | | |
| service_instance_guid=$(cf service bookshop-mt-uaa --guid) | |
| if [ -z "$service_instance_guid" ]; then | |
| echo "β Error: Unable to retrieve service instance GUID"; exit 1; | |
| fi | |
| bindings_response=$(cf curl "/v3/service_credential_bindings?service_instance_guids=${service_instance_guid}") | |
| binding_guid=$(echo "$bindings_response" | jq -r '.resources[0].guid') | |
| if [ -z "$binding_guid" ]; then | |
| echo "β Error: Unable to retrieve binding GUID"; exit 1; | |
| fi | |
| binding_details=$(cf curl "/v3/service_credential_bindings/${binding_guid}/details") | |
| clientSecret_mt=$(echo "$binding_details" | jq -r '.credentials.clientsecret') | |
| if [ -z "$clientSecret_mt" ] || [ "$clientSecret_mt" == "null" ]; then | |
| echo "β Error: clientSecret_mt is not set or is null"; exit 1; | |
| fi | |
| escapedClientSecret_mt=$(echo "$clientSecret_mt" | sed 's/\$/\\$/g') | |
| echo "::add-mask::$escapedClientSecret_mt" | |
| clientID_mt=$(echo "$binding_details" | jq -r '.credentials.clientid') | |
| if [ -z "$clientID_mt" ] || [ "$clientID_mt" == "null" ]; then | |
| echo "β Error: clientID_mt is not set or is null"; exit 1; | |
| fi | |
| echo "::add-mask::$clientID_mt" | |
| echo "CLIENT_SECRET_MT=$escapedClientSecret_mt" >> $GITHUB_OUTPUT | |
| echo "CLIENT_ID_MT=$clientID_mt" >> $GITHUB_OUTPUT | |
| - name: Run all subscription integration tests π― | |
| id: run_tests | |
| env: | |
| CLIENT_SECRET: ${{ steps.fetch_credentials.outputs.CLIENT_SECRET }} | |
| CLIENT_ID: ${{ steps.fetch_credentials.outputs.CLIENT_ID }} | |
| CLIENT_SECRET_MT: ${{ steps.fetch_credentials_mt.outputs.CLIENT_SECRET_MT }} | |
| CLIENT_ID_MT: ${{ steps.fetch_credentials_mt.outputs.CLIENT_ID_MT }} | |
| CMIS_CLIENT_ID: ${{ secrets.CMISCLIENTID }} | |
| CMIS_CLIENT_SECRET: ${{ secrets.CMISCLIENTSECRET }} | |
| run: | | |
| set -e | |
| PROPERTIES_FILE="sdm/src/test/resources/credentials.properties" | |
| appUrl="${{ secrets.CF_ORG }}-${{ steps.determine_space.outputs.space }}-demoappjava-srv.cfapps.eu12.hana.ondemand.com" | |
| appUrlMT="${{ secrets.CF_ORG }}-${{ steps.determine_space.outputs.space }}-bookshop-mt-srv.cfapps.eu12.hana.ondemand.com" | |
| authUrl="${{ secrets.CAPAUTH_URL }}" | |
| authUrlMT1="${{ secrets.AUTHURLMT1 }}" | |
| authUrlMT2="${{ secrets.AUTHURLMT2 }}" | |
| clientID="${{ env.CLIENT_ID }}" | |
| clientSecret="${{ env.CLIENT_SECRET }}" | |
| clientIDMT="${{ env.CLIENT_ID_MT }}" | |
| clientSecretMT="${{ env.CLIENT_SECRET_MT }}" | |
| username="${{ secrets.CF_USER }}" | |
| password="${{ secrets.CF_PASSWORD }}" | |
| noSDMRoleUsername="${{ secrets.NOSDMROLEUSERNAME }}" | |
| noSDMRoleUserPassword="${{ secrets.NOSDMROLEUSERPASSWORD }}" | |
| versionedRepositoryID="${{ secrets.VERSIONEDREPOSITORYID }}" | |
| virusScanRepositoryID="${{ secrets.VIRUSSCANREPOSITORYID }}" | |
| defaultRepositoryID="${{ secrets.DEFAULTREPOSITORYID }}" | |
| defaultRepositoryIDMT="${{ secrets.DEFAULTREPOSITORYIDMT }}" | |
| consumerSubaccountIdMT1="${{ secrets.CONSUMERSUBACCOUNTIDMT1 }}" | |
| consumerSubdomainMT1="${{ secrets.CONSUMERSUBDOMAINMT1 }}" | |
| consumerSubaccountIdMT2="${{ secrets.CONSUMERSUBACCOUNTIDMT2 }}" | |
| consumerSubdomainMT2="${{ secrets.CONSUMERSUBDOMAINMT2 }}" | |
| consumerSubdomainMT="${{ secrets.CONSUMERSUBDOMAINMT }}" | |
| CMIS_URL="${{ secrets.CMIS_URL }}" | |
| cmisClientID="$CMIS_CLIENT_ID" | |
| cmisClientSecret="$CMIS_CLIENT_SECRET" | |
| SAAS_APP_NAME="bookshop-mt-sdmgoogleworkspacedev-${{ steps.determine_space.outputs.space }}" | |
| ROLE_COLLECTION_NAME="ak-test" | |
| APP_ROLE_FILTER="bookshop-mt-sdmgoogleworkspacedev-${{ steps.determine_space.outputs.space }}" | |
| BTP_CLI_URL="${{ secrets.BTP_CLI_URL }}" | |
| BTP_GLOBAL_ACCOUNT_SUBDOMAIN="${{ secrets.BTP_GLOBAL_ACCOUNT_SUBDOMAIN }}" | |
| FAILED=0 | |
| for tenant in TENANT1 TENANT2; do | |
| echo "π― Running subscription test for $tenant" | |
| cat > "$PROPERTIES_FILE" <<EOL | |
| appUrl=$appUrl | |
| appUrlMT=$appUrlMT | |
| authUrl=$authUrl | |
| authUrlMT1=$authUrlMT1 | |
| authUrlMT2=$authUrlMT2 | |
| clientID=$clientID | |
| clientSecret=$clientSecret | |
| clientIDMT=$clientIDMT | |
| clientSecretMT=$clientSecretMT | |
| username=$username | |
| password=$password | |
| noSDMRoleUsername=$noSDMRoleUsername | |
| noSDMRoleUserPassword=$noSDMRoleUserPassword | |
| versionedRepositoryID=$versionedRepositoryID | |
| virusScanRepositoryID=$virusScanRepositoryID | |
| defaultRepositoryID=$defaultRepositoryID | |
| defaultRepositoryIDMT=$defaultRepositoryIDMT | |
| consumerSubaccountIdMT1=$consumerSubaccountIdMT1 | |
| consumerSubdomainMT1=$consumerSubdomainMT1 | |
| consumerSubaccountIdMT2=$consumerSubaccountIdMT2 | |
| consumerSubdomainMT2=$consumerSubdomainMT2 | |
| CMIS_URL=$CMIS_URL | |
| cmisClientID=$cmisClientID | |
| cmisClientSecret=$cmisClientSecret | |
| SAAS_APP_NAME=$SAAS_APP_NAME | |
| ROLE_COLLECTION_NAME=$ROLE_COLLECTION_NAME | |
| APP_ROLE_FILTER=$APP_ROLE_FILTER | |
| BTP_CLI_URL=$BTP_CLI_URL | |
| BTP_GLOBAL_ACCOUNT_SUBDOMAIN=$BTP_GLOBAL_ACCOUNT_SUBDOMAIN | |
| EOL | |
| if ! mvn clean verify -P integration-tests \ | |
| -DtokenFlow=technicalUser -DtenancyModel=multi -Dtenant=$tenant \ | |
| -DskipUnitTests -Dfailsafe.includes="**/IntegrationTest_Subscription.java"; then | |
| echo "β FAILED: subscription test - $tenant" | |
| FAILED=$((FAILED + 1)) | |
| else | |
| echo "β PASSED: subscription test - $tenant" | |
| fi | |
| done | |
| if [ $FAILED -gt 0 ]; then | |
| echo "β $FAILED subscription test(s) failed" | |
| exit 1 | |
| fi | |
| # Summary job to aggregate results | |
| test-summary: | |
| runs-on: ubuntu-latest | |
| needs: [integration-test, versioned-test, virusscan-test, virusscan-cleanup, repospecific-test, subscription-test] | |
| if: "!cancelled()" | |
| steps: | |
| - name: Check test results π | |
| run: | | |
| echo "Integration test: ${{ needs.integration-test.result }}" | |
| echo "Versioned test: ${{ needs.versioned-test.result }}" | |
| echo "Virus scan test: ${{ needs.virusscan-test.result }}" | |
| echo "Repo-specific test: ${{ needs.repospecific-test.result }}" | |
| echo "Subscription test: ${{ needs.subscription-test.result }}" | |
| if [ "${{ needs.integration-test.result }}" == "success" ] && \ | |
| [ "${{ needs.versioned-test.result }}" == "success" ] && \ | |
| [ "${{ needs.virusscan-test.result }}" == "success" ] && \ | |
| [ "${{ needs.repospecific-test.result }}" == "success" ] && \ | |
| [ "${{ needs.subscription-test.result }}" == "success" ]; then | |
| echo "β All integration tests passed!" | |
| else | |
| echo "β Some integration tests failed. Check individual job results for details." | |
| exit 1 | |
| fi |