From 8ecc577ff9561ba7015a168bb86f593373040573 Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Mon, 4 May 2026 13:39:47 +0200 Subject: [PATCH 01/21] . --- .github/actions/build/action.yml | 12 +- .github/actions/deploy-release/action.yml | 10 +- .github/actions/integration-tests/action.yml | 4 +- .github/actions/newrelease/action.yml | 4 +- .../actions/scan-with-blackduck/action.yml | 37 +++--- .github/actions/scan-with-sonar/action.yml | 32 ++--- .github/actions/test-sample/action.yml | 14 ++- .github/dependabot.yml | 1 + .github/workflows/issue.yml | 9 +- .github/workflows/main.yml | 26 +++- .github/workflows/pipeline.yml | 117 +++++++----------- .github/workflows/pr.yml | 24 +++- .github/workflows/prevent-issue-labeling.yml | 5 +- .github/workflows/release.yml | 21 ++-- .github/workflows/stale.yml | 5 +- .pipeline/config.yml | 52 -------- 16 files changed, 173 insertions(+), 200 deletions(-) delete mode 100644 .pipeline/config.yml diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index a6fd34568..629ef1d9b 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -17,22 +17,20 @@ runs: using: composite steps: - name: Set up Java ${{ inputs.java-version }} - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: ${{ inputs.java-version }} distribution: sapmachine cache: maven - name: Set up Maven ${{ inputs.maven-version }} - uses: stCarolas/setup-maven@v5 + uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5 with: maven-version: ${{ inputs.maven-version }} - - name: Piper Maven build - uses: SAP/project-piper-action@main - with: - step-name: mavenBuild - docker-image: '' + - name: Maven Build + run: mvn clean install -DskipTests -B -ntp + shell: bash - name: Mutation Testing if: ${{ inputs.mutation-testing == 'true' }} diff --git a/.github/actions/deploy-release/action.yml b/.github/actions/deploy-release/action.yml index 23377a50c..7b900da65 100644 --- a/.github/actions/deploy-release/action.yml +++ b/.github/actions/deploy-release/action.yml @@ -27,14 +27,8 @@ inputs: runs: using: composite steps: - - name: Echo Inputs - run: | - echo "user: ${{ inputs.user }}" - echo "revision: ${{ inputs.revision }}" - shell: bash - - name: Set up Java - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: distribution: sapmachine java-version: '17' @@ -44,7 +38,7 @@ runs: server-password: MAVEN_CENTRAL_PASSWORD - name: Set up Maven ${{ inputs.maven-version }} - uses: stCarolas/setup-maven@v5 + uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5 with: maven-version: ${{ inputs.maven-version }} diff --git a/.github/actions/integration-tests/action.yml b/.github/actions/integration-tests/action.yml index ca4e3cfc1..0eb255882 100644 --- a/.github/actions/integration-tests/action.yml +++ b/.github/actions/integration-tests/action.yml @@ -16,14 +16,14 @@ runs: using: composite steps: - name: Set up Java ${{ inputs.java-version }} - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: ${{ inputs.java-version }} distribution: sapmachine cache: maven - name: Setup Maven ${{ inputs.maven-version }} - uses: stCarolas/setup-maven@v5 + uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5 with: maven-version: ${{ inputs.maven-version }} diff --git a/.github/actions/newrelease/action.yml b/.github/actions/newrelease/action.yml index a6fe732c4..e9a08a852 100644 --- a/.github/actions/newrelease/action.yml +++ b/.github/actions/newrelease/action.yml @@ -13,14 +13,14 @@ runs: using: composite steps: - name: Set up Java ${{ inputs.java-version }} - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: ${{ inputs.java-version }} distribution: sapmachine cache: maven - name: Set up Maven ${{ inputs.maven-version }} - uses: stCarolas/setup-maven@v5 + uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5 with: maven-version: ${{ inputs.maven-version }} diff --git a/.github/actions/scan-with-blackduck/action.yml b/.github/actions/scan-with-blackduck/action.yml index 2c847e382..2e69261ce 100644 --- a/.github/actions/scan-with-blackduck/action.yml +++ b/.github/actions/scan-with-blackduck/action.yml @@ -24,35 +24,40 @@ runs: using: composite steps: - name: Set up Java ${{ inputs.java-version }} - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: ${{ inputs.java-version }} distribution: sapmachine cache: maven - name: Set up Maven ${{ inputs.maven-version }} - uses: stCarolas/setup-maven@v5 + uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5 with: maven-version: ${{ inputs.maven-version }} - - name: Get Major Version - id: get-major-version + - name: Get Revision + id: get-revision run: | echo "REVISION=$(mvn help:evaluate -Dexpression=revision -q -DforceStdout)" >> $GITHUB_OUTPUT shell: bash - - name: Print Version Number - run: echo "${{ steps.get-major-version.outputs.REVISION }}" + - name: BlackDuck Detect Scan + run: | + bash <(curl -s -L https://detect.synopsys.com/detect9.sh) \ + --blackduck.url=https://sap.blackducksoftware.com/ \ + --blackduck.api.token="${BLACKDUCK_TOKEN}" \ + --detect.project.name=com.sap.cds.feature.attachments \ + --detect.project.version.name="${REVISION}" \ + --detect.included.detector.types=MAVEN \ + --detect.excluded.directories='**/node_modules,**/*test*,**/localrepo,**/target/site,**/*-site.jar,**/samples/**' \ + --detect.maven.excluded.modules=integration-tests,integration-tests/db,integration-tests/generic,integration-tests/mtx-local/srv \ + --detect.maven.build.command='-pl com.sap.cds:cds-feature-attachments' \ + --detect.tools=DETECTOR,BINARY_SCAN \ + --detect.blackduck.scan.mode="${SCAN_MODE}" \ + --detect.risk.report.pdf=false \ + --logging.level.detect=INFO shell: bash - - - name: BlackDuck Scan - uses: SAP/project-piper-action@main - with: - step-name: detectExecuteScan - flags: \ - --githubToken=$GITHUB_token \ - --version=${{ steps.get-major-version.outputs.REVISION }} env: - PIPER_token: ${{ inputs.blackduck_token }} - GITHUB_token: ${{ inputs.github_token }} + BLACKDUCK_TOKEN: ${{ inputs.blackduck_token }} SCAN_MODE: ${{ inputs.scan_mode }} + REVISION: ${{ steps.get-revision.outputs.REVISION }} diff --git a/.github/actions/scan-with-sonar/action.yml b/.github/actions/scan-with-sonar/action.yml index 3884b4052..a39d76125 100644 --- a/.github/actions/scan-with-sonar/action.yml +++ b/.github/actions/scan-with-sonar/action.yml @@ -20,14 +20,14 @@ runs: steps: - name: Set up Java ${{inputs.java-version}} - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: ${{inputs.java-version}} distribution: sapmachine cache: maven - name: Set up Maven ${{inputs.maven-version}} - uses: stCarolas/setup-maven@v5 + uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5 with: maven-version: ${{inputs.maven-version}} @@ -37,10 +37,6 @@ runs: echo "REVISION=$(mvn help:evaluate -Dexpression=revision -q -DforceStdout)" >> $GITHUB_OUTPUT shell: bash - - name: Print Revision - run: echo "${{steps.get-revision.outputs.REVISION}}" - shell: bash - - name: Build project for SonarQube scan run: | mvn clean verify -ntp -B @@ -66,12 +62,18 @@ runs: shell: bash - name: SonarQube Scan - uses: SAP/project-piper-action@main - with: - step-name: sonarExecuteScan - flags: > - --token=${{ inputs.sonarq-token }} - --githubToken=${{ inputs.github-token }} - --version=${{ steps.get-revision.outputs.REVISION }} - --inferJavaBinaries=true - --options=-Dsonar.exclusions=**/samples/**,-Dsonar.coverage.jacoco.xmlReportPaths=coverage-report/target/site/jacoco-aggregate/jacoco.xml + run: > + mvn org.sonarsource.scanner.maven:sonar-maven-plugin:sonar + -Dsonar.host.url=https://sonar.tools.sap + -Dsonar.token=${{ inputs.sonarq-token }} + -Dsonar.projectKey=cds-feature-attachments + -Dsonar.projectVersion=${{ steps.get-revision.outputs.REVISION }} + -Dsonar.qualitygate.wait=true + -Dsonar.java.source=17 + -Dsonar.exclusions=**/samples/** + -Dsonar.coverage.jacoco.xmlReportPaths=coverage-report/target/site/jacoco-aggregate/jacoco.xml + -Dsonar.coverage.exclusions=cds-feature-attachments/src/test/**,cds-feature-attachments/src/gen/**,storage-targets/cds-feature-attachments-fs/src/test/**,storage-targets/cds-feature-attachments-oss/src/test/** + -B -ntp + shell: bash + env: + GITHUB_TOKEN: ${{ inputs.github-token }} diff --git a/.github/actions/test-sample/action.yml b/.github/actions/test-sample/action.yml index 403d49584..c0c8954f2 100644 --- a/.github/actions/test-sample/action.yml +++ b/.github/actions/test-sample/action.yml @@ -1,18 +1,26 @@ name: 'Test Sample' description: 'Compile sample and run tests' +inputs: + java-version: + description: The Java version the build shall run with. + required: true + maven-version: + description: The Maven version the build shall run with. + required: true + runs: using: 'composite' steps: - name: Set up Java ${{ inputs.java-version }} - uses: actions/setup-java@v4 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: ${{ inputs.java-version }} distribution: sapmachine cache: maven - name: Set up Maven ${{ inputs.maven-version }} - uses: stCarolas/setup-maven@v5 + uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5 with: maven-version: ${{ inputs.maven-version }} @@ -29,4 +37,4 @@ runs: - name: Run tests shell: bash working-directory: samples/bookshop - run: mvn test \ No newline at end of file + run: mvn test diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f5cd6b22c..cb2acf71c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -21,6 +21,7 @@ updates: directory: "/" schedule: interval: weekly + open-pull-requests-limit: 5 groups: minor-patch: patterns: diff --git a/.github/workflows/issue.yml b/.github/workflows/issue.yml index ef40728ee..f0ce52ea9 100644 --- a/.github/workflows/issue.yml +++ b/.github/workflows/issue.yml @@ -1,7 +1,6 @@ name: Label issues -permissions: - issues: write +permissions: {} on: issues: @@ -11,6 +10,8 @@ on: jobs: label_issues: runs-on: ubuntu-latest + permissions: + issues: write steps: - run: gh issue edit "$NUMBER" --add-label "$LABELS" env: @@ -19,7 +20,7 @@ jobs: NUMBER: ${{ github.event.issue.number }} LABELS: New - - uses: actions/github-script@v9 + - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 with: script: | github.rest.issues.createComment({ @@ -27,4 +28,4 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, body: `👋 Hello @${context.payload.issue.user.login}, thank you for submitting this issue. Our team is reviewing your report and will follow up with you as soon as possible.` - }) \ No newline at end of file + }) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e077dd447..c6ba8e5b1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,5 +1,7 @@ name: CI - MAIN +permissions: read-all + env: MAVEN_VERSION: '3.9.12' @@ -15,7 +17,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Scan With Black Duck uses: ./.github/actions/scan-with-blackduck @@ -27,6 +29,22 @@ jobs: build-and-test: uses: ./.github/workflows/pipeline.yml - with: - deploy-snapshot: true - secrets: inherit \ No newline at end of file + secrets: + AWS_S3_HOST: ${{ secrets.AWS_S3_HOST }} + AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} + AWS_S3_REGION: ${{ secrets.AWS_S3_REGION }} + AWS_S3_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} + AWS_S3_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} + AZURE_CONTAINER_URI: ${{ secrets.AZURE_CONTAINER_URI }} + AZURE_SAS_TOKEN: ${{ secrets.AZURE_SAS_TOKEN }} + GS_BASE_64_ENCODED_PRIVATE_KEY_DATA: ${{ secrets.GS_BASE_64_ENCODED_PRIVATE_KEY_DATA }} + GS_BUCKET: ${{ secrets.GS_BUCKET }} + GS_PROJECT_ID: ${{ secrets.GS_PROJECT_ID }} + MALWARE_SCANNER_URL: ${{ secrets.MALWARE_SCANNER_URL }} + MALWARE_SCANNER_USERNAME: ${{ secrets.MALWARE_SCANNER_USERNAME }} + MALWARE_SCANNER_PASSWORD: ${{ secrets.MALWARE_SCANNER_PASSWORD }} + MALWARE_SCANNER_MTLS_URI: ${{ secrets.MALWARE_SCANNER_MTLS_URI }} + MALWARE_SCANNER_MTLS_CERTIFICATE: ${{ secrets.MALWARE_SCANNER_MTLS_CERTIFICATE }} + MALWARE_SCANNER_MTLS_KEY: ${{ secrets.MALWARE_SCANNER_MTLS_KEY }} + SONARQ_TOKEN: ${{ secrets.SONARQ_TOKEN }} + GH_TOKEN: ${{ secrets.GH_TOKEN }} diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 8a7da8016..0374c64e6 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -1,15 +1,49 @@ name: Reusable Workflow +permissions: read-all + env: MAVEN_VERSION: '3.9.12' on: workflow_call: - inputs: - deploy-snapshot: + secrets: + AWS_S3_HOST: + required: true + AWS_S3_BUCKET: + required: true + AWS_S3_REGION: + required: true + AWS_S3_ACCESS_KEY_ID: + required: true + AWS_S3_SECRET_ACCESS_KEY: + required: true + AZURE_CONTAINER_URI: + required: true + AZURE_SAS_TOKEN: + required: true + GS_BASE_64_ENCODED_PRIVATE_KEY_DATA: + required: true + GS_BUCKET: + required: true + GS_PROJECT_ID: + required: true + MALWARE_SCANNER_URL: + required: true + MALWARE_SCANNER_USERNAME: + required: true + MALWARE_SCANNER_PASSWORD: + required: true + MALWARE_SCANNER_MTLS_URI: + required: true + MALWARE_SCANNER_MTLS_CERTIFICATE: + required: true + MALWARE_SCANNER_MTLS_KEY: + required: true + SONARQ_TOKEN: + required: true + GH_TOKEN: required: true - type: boolean - default: false jobs: build: @@ -21,10 +55,8 @@ jobs: java-version: [ 17, 21 ] steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: - # For internal PRs (same repo), checkout PR head to test actual changes - # For external PRs (forks), checkout base branch for security ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} - name: Spotless check @@ -37,7 +69,7 @@ jobs: maven-version: ${{ env.MAVEN_VERSION }} - name: Upload build artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: build-artifacts-java-${{ matrix.java-version }} path: | @@ -52,24 +84,19 @@ jobs: timeout-minutes: 30 needs: build env: - ## AWS AWS_S3_HOST: ${{ secrets.AWS_S3_HOST }} AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} AWS_S3_REGION: ${{ secrets.AWS_S3_REGION }} AWS_S3_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} AWS_S3_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} - ## Azure AZURE_CONTAINER_URI: ${{ secrets.AZURE_CONTAINER_URI }} AZURE_SAS_TOKEN: ${{ secrets.AZURE_SAS_TOKEN }} - ## GCP GS_BASE_64_ENCODED_PRIVATE_KEY_DATA: ${{ secrets.GS_BASE_64_ENCODED_PRIVATE_KEY_DATA }} GS_BUCKET: ${{ secrets.GS_BUCKET }} GS_PROJECT_ID: ${{ secrets.GS_PROJECT_ID }} - ## Malware Scanner (Basic Auth) MALWARE_SCANNER_URL: ${{ secrets.MALWARE_SCANNER_URL }} MALWARE_SCANNER_USERNAME: ${{ secrets.MALWARE_SCANNER_USERNAME }} MALWARE_SCANNER_PASSWORD: ${{ secrets.MALWARE_SCANNER_PASSWORD }} - ## Malware Scanner (mTLS) MALWARE_SCANNER_MTLS_URI: ${{ secrets.MALWARE_SCANNER_MTLS_URI }} MALWARE_SCANNER_MTLS_CERTIFICATE: ${{ secrets.MALWARE_SCANNER_MTLS_CERTIFICATE }} MALWARE_SCANNER_MTLS_KEY: ${{ secrets.MALWARE_SCANNER_MTLS_KEY }} @@ -80,12 +107,12 @@ jobs: test-type: [ build-version, latest-version, oss ] steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} - name: Download build artifacts - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: name: build-artifacts-java-${{ matrix.java-version }} @@ -103,7 +130,7 @@ jobs: needs: build steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} - name: SonarQube Scan @@ -126,19 +153,19 @@ jobs: contents: read steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} - name: Set up Java - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: '17' distribution: 'sapmachine' cache: 'maven' - name: Initialize CodeQL - uses: github/codeql-action/init@v4 + uses: github/codeql-action/init@ed410739ba306e4ebe5e123421a6bd694e494a2b # v4 with: languages: java-kotlin build-mode: manual @@ -147,56 +174,6 @@ jobs: run: mvn clean compile -DskipTests -B -ntp - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 + uses: github/codeql-action/analyze@ed410739ba306e4ebe5e123421a6bd694e494a2b # v4 with: category: "/language:java-kotlin" - - deploy-snapshot: - name: Deploy snapshot to Artifactory - runs-on: ubuntu-latest - timeout-minutes: 30 - if: ${{ inputs.deploy-snapshot == true }} - needs: [build, integration-tests, codeql] - steps: - - name: Checkout - uses: actions/checkout@v6 - with: - ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} - - - name: Set up Java - uses: actions/setup-java@v5 - with: - java-version: '17' - distribution: 'sapmachine' - cache: 'maven' - server-id: artifactory - server-username: DEPLOYMENT_USER - server-password: DEPLOYMENT_PASS - - - name: Set up Maven ${{ env.MAVEN_VERSION }} - uses: stCarolas/setup-maven@v5 - with: - maven-version: ${{ env.MAVEN_VERSION }} - - - name: Set Dry Run for Pull Request - if: github.event_name == 'pull_request_target' - run: echo "DRY_RUN_PARAM=-DaltDeploymentRepository=local-repo::default::file:./local-repo" >> $GITHUB_ENV - shell: bash - - - name: Get Revision - id: get-revision - run: | - echo "REVISION=$(mvn help:evaluate -Dexpression=revision -q -DforceStdout)" >> $GITHUB_OUTPUT - shell: bash - - - name: Print Revision - run: echo "Current revision ${{ steps.get-revision.outputs.REVISION }}" - shell: bash - - - name: Deploy snapshot - if: ${{ endsWith(steps.get-revision.outputs.REVISION, '-SNAPSHOT') }} - run: mvn -B -ntp -fae -pl !integration-tests,!integration-tests/db,!integration-tests/generic,!integration-tests/mtx-local/srv -Dmaven.install.skip=true -Dmaven.test.skip=true -DdeployAtEnd=true deploy - env: - DEPLOYMENT_USER: ${{ secrets.DEPLOYMENT_USER }} - DEPLOYMENT_PASS: ${{ secrets.DEPLOYMENT_PASS }} - shell: bash diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index a98b55823..48962c712 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -1,5 +1,7 @@ name: CI - PR +permissions: read-all + on: workflow_dispatch: pull_request_target: @@ -20,6 +22,22 @@ jobs: needs: requires-approval if: always() && (needs.requires-approval.result == 'success' || needs.requires-approval.result == 'skipped') uses: ./.github/workflows/pipeline.yml - with: - deploy-snapshot: false - secrets: inherit \ No newline at end of file + secrets: + AWS_S3_HOST: ${{ secrets.AWS_S3_HOST }} + AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} + AWS_S3_REGION: ${{ secrets.AWS_S3_REGION }} + AWS_S3_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} + AWS_S3_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} + AZURE_CONTAINER_URI: ${{ secrets.AZURE_CONTAINER_URI }} + AZURE_SAS_TOKEN: ${{ secrets.AZURE_SAS_TOKEN }} + GS_BASE_64_ENCODED_PRIVATE_KEY_DATA: ${{ secrets.GS_BASE_64_ENCODED_PRIVATE_KEY_DATA }} + GS_BUCKET: ${{ secrets.GS_BUCKET }} + GS_PROJECT_ID: ${{ secrets.GS_PROJECT_ID }} + MALWARE_SCANNER_URL: ${{ secrets.MALWARE_SCANNER_URL }} + MALWARE_SCANNER_USERNAME: ${{ secrets.MALWARE_SCANNER_USERNAME }} + MALWARE_SCANNER_PASSWORD: ${{ secrets.MALWARE_SCANNER_PASSWORD }} + MALWARE_SCANNER_MTLS_URI: ${{ secrets.MALWARE_SCANNER_MTLS_URI }} + MALWARE_SCANNER_MTLS_CERTIFICATE: ${{ secrets.MALWARE_SCANNER_MTLS_CERTIFICATE }} + MALWARE_SCANNER_MTLS_KEY: ${{ secrets.MALWARE_SCANNER_MTLS_KEY }} + SONARQ_TOKEN: ${{ secrets.SONARQ_TOKEN }} + GH_TOKEN: ${{ secrets.GH_TOKEN }} diff --git a/.github/workflows/prevent-issue-labeling.yml b/.github/workflows/prevent-issue-labeling.yml index dac7a41b3..6c3503090 100644 --- a/.github/workflows/prevent-issue-labeling.yml +++ b/.github/workflows/prevent-issue-labeling.yml @@ -1,7 +1,6 @@ name: Prevent "New" Label on Issues -permissions: - issues: write +permissions: {} on: issues: @@ -10,6 +9,8 @@ on: jobs: remove_new_label: runs-on: ubuntu-latest + permissions: + issues: write steps: - name: Remove "New" label if applied by non-bot user if: > diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 422008ff2..8bccdaa10 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,5 +1,7 @@ name: Deploy to Maven Central +permissions: read-all + env: JAVA_VERSION: '17' MAVEN_VERSION: '3.9.12' @@ -15,7 +17,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Scan With Black Duck uses: ./.github/actions/scan-with-blackduck @@ -28,9 +30,11 @@ jobs: name: Update Version runs-on: ubuntu-latest timeout-minutes: 30 + permissions: + contents: write steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: token: ${{ secrets.GH_TOKEN }} @@ -41,11 +45,10 @@ jobs: maven-version: ${{ env.MAVEN_VERSION }} - name: Upload Changed Artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: root-new-version path: . - include-hidden-files: true retention-days: 1 build: @@ -66,7 +69,7 @@ jobs: GS_PROJECT_ID: ${{ secrets.GS_PROJECT_ID }} steps: - name: Download artifact - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: name: root-new-version @@ -85,10 +88,9 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} - name: Upload Changed Artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: root-build - include-hidden-files: true path: . retention-days: 1 @@ -99,7 +101,7 @@ jobs: needs: [blackduck, build] steps: - name: Download artifact - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: name: root-build @@ -113,6 +115,3 @@ jobs: pgp-passphrase: ${{ secrets.PGP_PASSPHRASE }} revision: ${{ github.event.release.tag_name }} maven-version: ${{ env.MAVEN_VERSION }} - - - name: Echo Status - run: echo "The job status is ${{ job.status }}" diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 3e33f1df1..4feaa66fb 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,4 +1,7 @@ name: "Close stale issues" + +permissions: {} + on: schedule: - cron: "30 1 * * *" @@ -11,7 +14,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@v10 + - uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10 with: close-issue-message: "This issue has been automatically closed due to 2 weeks of inactivity. If you believe this was a mistake, please reopen or comment to continue the discussion." days-before-stale: -1 diff --git a/.pipeline/config.yml b/.pipeline/config.yml deleted file mode 100644 index 111191b00..000000000 --- a/.pipeline/config.yml +++ /dev/null @@ -1,52 +0,0 @@ -steps: - mavenBuild: - verbose: false - verify: false - flatten: true - # https://www.project-piper.io/steps/mavenBuild/#dockerimage - # If empty, Docker is not used and the command is executed directly on the Jenkins system. - dockerImage: '' - - detectExecuteScan: - projectName: 'com.sap.cds.feature.attachments' - groups: - - 'CDSJAVA-OPEN-SOURCE' - serverUrl: 'https://sap.blackducksoftware.com/' - mavenExcludedScopes: [ "provided", "test" ] - failOn: [ 'NONE' ] - versioningModel: "major-minor" - detectTools: [ 'DETECTOR', 'BINARY_SCAN' ] - installArtifacts: false - repository: '/cap-java/cds-feature-attachments' - verbose: true - scanProperties: - - --detect.included.detector.types=MAVEN - - --detect.excluded.directories='**/node_modules,**/*test*,**/localrepo,**/target/site,**/*-site.jar,**/samples/**' - - --detect.maven.excluded.modules=integration-tests,integration-tests/db,integration-tests/generic,integration-tests/mtx-local/srv - - --detect.maven.build.command='-pl com.sap.cds:cds-feature-attachments' - # https://www.project-piper.io/steps/detectExecuteScan/#dockerimage - # If empty, Docker is not used and the command is executed directly on the Jenkins system. - dockerImage: '' - - sonarExecuteScan: - serverUrl: https://sonar.tools.sap - projectKey: cds-feature-attachments - options: - - sonar.qualitygate.wait=true - - sonar.java.source=17 - - sonar.exclusions=**/node_modules/**,**/target/**,**/test/** - - sonar.modules=cds-feature-attachments,cds-feature-attachments-fs,cds-feature-attachments-oss - - sonar.coverage.jacoco.xmlReportPaths=coverage-report/target/site/jacoco-aggregate/jacoco.xml - - sonar.coverage.exclusions=cds-feature-attachments/src/test/**,cds-feature-attachments/src/gen/**,storage-targets/cds-feature-attachments-fs/src/test/**,storage-targets/cds-feature-attachments-oss/src/test/** - - cds-feature-attachments.sonar.projectBaseDir=cds-feature-attachments - - cds-feature-attachments.sonar.sources=src/main/java - - cds-feature-attachments.sonar.tests=src/test/java - - cds-feature-attachments.sonar.java.binaries=target/classes - - cds-feature-attachments-fs.sonar.projectBaseDir=storage-targets/cds-feature-attachments-fs - - cds-feature-attachments-fs.sonar.sources=src/main/java - - cds-feature-attachments-fs.sonar.tests=src/test/java - - cds-feature-attachments-fs.sonar.java.binaries=target/classes - - cds-feature-attachments-oss.sonar.projectBaseDir=storage-targets/cds-feature-attachments-oss - - cds-feature-attachments-oss.sonar.sources=src/main/java - - cds-feature-attachments-oss.sonar.tests=src/test/java - - cds-feature-attachments-oss.sonar.java.binaries=target/classes From 526714364da5e46930134b571e7fa3d2b09b2dfd Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Mon, 4 May 2026 15:09:30 +0200 Subject: [PATCH 02/21] update --- .github/actions/build/action.yml | 9 --- .github/actions/integration-tests/action.yml | 3 + .github/workflows/pipeline.yml | 85 +++++++++++--------- 3 files changed, 48 insertions(+), 49 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 629ef1d9b..8982a2149 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -8,10 +8,6 @@ inputs: maven-version: description: The Maven version the build will run with. required: true - mutation-testing: - description: Whether to run mutation testing or not. - default: 'true' - required: false runs: using: composite @@ -31,8 +27,3 @@ runs: - name: Maven Build run: mvn clean install -DskipTests -B -ntp shell: bash - - - name: Mutation Testing - if: ${{ inputs.mutation-testing == 'true' }} - run: mvn org.pitest:pitest-maven:mutationCoverage -f cds-feature-attachments/pom.xml -ntp -B - shell: bash diff --git a/.github/actions/integration-tests/action.yml b/.github/actions/integration-tests/action.yml index 0eb255882..8be8de2ab 100644 --- a/.github/actions/integration-tests/action.yml +++ b/.github/actions/integration-tests/action.yml @@ -11,6 +11,9 @@ inputs: test-type: description: 'Which integration test to run: build-version, latest-version, or oss' required: true + auth-method: + description: 'Authentication method: basic or mtls' + required: true runs: using: composite diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 0374c64e6..b532e7ca4 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -46,43 +46,41 @@ on: required: true jobs: - build: - name: Build (Java ${{ matrix.java-version }}) + spotless: + name: Spotless Check runs-on: ubuntu-latest - timeout-minutes: 30 - strategy: - matrix: - java-version: [ 17, 21 ] + timeout-minutes: 10 steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} - - name: Spotless check - run: mvn spotless:check -Dspotless.check.skip=false + - name: Set up Java + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: '17' + distribution: sapmachine + cache: maven - - name: Build - uses: ./.github/actions/build + - name: Set up Maven + uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5 with: - java-version: ${{ matrix.java-version }} maven-version: ${{ env.MAVEN_VERSION }} - - name: Upload build artifacts - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 - with: - name: build-artifacts-java-${{ matrix.java-version }} - path: | - **/target/*.jar - **/pom.xml - .mvn/ - retention-days: 1 + - name: Spotless Check + run: mvn spotless:check -Dspotless.check.skip=false -B -ntp integration-tests: - name: Integration Tests (Java ${{ matrix.java-version }}, ${{ matrix.test-type }}) + name: ITests (Java ${{ matrix.java-version }}, ${{ matrix.test-type }}, ${{ matrix.auth-method }}) runs-on: ubuntu-latest timeout-minutes: 30 - needs: build + strategy: + fail-fast: false + matrix: + java-version: [ 17, 21 ] + test-type: [ build-version, latest-version, oss ] + auth-method: [ basic, mtls ] env: AWS_S3_HOST: ${{ secrets.AWS_S3_HOST }} AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} @@ -94,45 +92,53 @@ jobs: GS_BASE_64_ENCODED_PRIVATE_KEY_DATA: ${{ secrets.GS_BASE_64_ENCODED_PRIVATE_KEY_DATA }} GS_BUCKET: ${{ secrets.GS_BUCKET }} GS_PROJECT_ID: ${{ secrets.GS_PROJECT_ID }} - MALWARE_SCANNER_URL: ${{ secrets.MALWARE_SCANNER_URL }} - MALWARE_SCANNER_USERNAME: ${{ secrets.MALWARE_SCANNER_USERNAME }} - MALWARE_SCANNER_PASSWORD: ${{ secrets.MALWARE_SCANNER_PASSWORD }} - MALWARE_SCANNER_MTLS_URI: ${{ secrets.MALWARE_SCANNER_MTLS_URI }} - MALWARE_SCANNER_MTLS_CERTIFICATE: ${{ secrets.MALWARE_SCANNER_MTLS_CERTIFICATE }} - MALWARE_SCANNER_MTLS_KEY: ${{ secrets.MALWARE_SCANNER_MTLS_KEY }} - strategy: - fail-fast: false - matrix: - java-version: [ 17, 21 ] - test-type: [ build-version, latest-version, oss ] + MALWARE_SCANNER_URL: ${{ matrix.auth-method == 'basic' && secrets.MALWARE_SCANNER_URL || '' }} + MALWARE_SCANNER_USERNAME: ${{ matrix.auth-method == 'basic' && secrets.MALWARE_SCANNER_USERNAME || '' }} + MALWARE_SCANNER_PASSWORD: ${{ matrix.auth-method == 'basic' && secrets.MALWARE_SCANNER_PASSWORD || '' }} + MALWARE_SCANNER_MTLS_URI: ${{ matrix.auth-method == 'mtls' && secrets.MALWARE_SCANNER_MTLS_URI || '' }} + MALWARE_SCANNER_MTLS_CERTIFICATE: ${{ matrix.auth-method == 'mtls' && secrets.MALWARE_SCANNER_MTLS_CERTIFICATE || '' }} + MALWARE_SCANNER_MTLS_KEY: ${{ matrix.auth-method == 'mtls' && secrets.MALWARE_SCANNER_MTLS_KEY || '' }} steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} - - name: Download build artifacts - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 - with: - name: build-artifacts-java-${{ matrix.java-version }} - - name: Integration Tests uses: ./.github/actions/integration-tests with: java-version: ${{ matrix.java-version }} maven-version: ${{ env.MAVEN_VERSION }} test-type: ${{ matrix.test-type }} + auth-method: ${{ matrix.auth-method }} sonarqube-scan: name: SonarQube Scan runs-on: ubuntu-latest timeout-minutes: 30 - needs: build + env: + AWS_S3_HOST: ${{ secrets.AWS_S3_HOST }} + AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} + AWS_S3_REGION: ${{ secrets.AWS_S3_REGION }} + AWS_S3_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} + AWS_S3_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} + AZURE_CONTAINER_URI: ${{ secrets.AZURE_CONTAINER_URI }} + AZURE_SAS_TOKEN: ${{ secrets.AZURE_SAS_TOKEN }} + GS_BASE_64_ENCODED_PRIVATE_KEY_DATA: ${{ secrets.GS_BASE_64_ENCODED_PRIVATE_KEY_DATA }} + GS_BUCKET: ${{ secrets.GS_BUCKET }} + GS_PROJECT_ID: ${{ secrets.GS_PROJECT_ID }} + MALWARE_SCANNER_URL: ${{ secrets.MALWARE_SCANNER_URL }} + MALWARE_SCANNER_USERNAME: ${{ secrets.MALWARE_SCANNER_USERNAME }} + MALWARE_SCANNER_PASSWORD: ${{ secrets.MALWARE_SCANNER_PASSWORD }} + MALWARE_SCANNER_MTLS_URI: ${{ secrets.MALWARE_SCANNER_MTLS_URI }} + MALWARE_SCANNER_MTLS_CERTIFICATE: ${{ secrets.MALWARE_SCANNER_MTLS_CERTIFICATE }} + MALWARE_SCANNER_MTLS_KEY: ${{ secrets.MALWARE_SCANNER_MTLS_KEY }} steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} + - name: SonarQube Scan uses: ./.github/actions/scan-with-sonar with: @@ -144,7 +150,6 @@ jobs: codeql: name: CodeQL Analysis runs-on: ubuntu-latest - needs: build timeout-minutes: 30 permissions: security-events: write From 3683cb6e6fa9b31627eab84efb300ee952458819 Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Mon, 4 May 2026 15:13:13 +0200 Subject: [PATCH 03/21] add default days --- .github/dependabot.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index cb2acf71c..8be0b3dbf 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,10 +5,8 @@ updates: - "/" schedule: interval: weekly - ignore: - - dependency-name: "com.sap.cds:*" - versions: - - ">=4" + cooldown: + default-days: 7 groups: minor-patch: patterns: @@ -21,7 +19,8 @@ updates: directory: "/" schedule: interval: weekly - open-pull-requests-limit: 5 + cooldown: + default-days: 7 groups: minor-patch: patterns: From 302f38cf9bd87980e45c152b608735de7f5109bf Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Mon, 4 May 2026 15:28:26 +0200 Subject: [PATCH 04/21] . --- .github/workflows/main.yml | 31 ++++++++----------------------- .github/workflows/pipeline.yml | 6 +++++- .github/workflows/pr.yml | 26 ++++++-------------------- 3 files changed, 19 insertions(+), 44 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c6ba8e5b1..307ffe844 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,9 +1,10 @@ name: CI - MAIN -permissions: read-all - -env: - MAVEN_VERSION: '3.9.12' +permissions: + actions: read + contents: read + packages: read + security-events: write on: workflow_dispatch: @@ -15,6 +16,8 @@ jobs: name: Blackduck Scan runs-on: ubuntu-latest timeout-minutes: 30 + env: + MAVEN_VERSION: '3.9.12' steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 @@ -29,22 +32,4 @@ jobs: build-and-test: uses: ./.github/workflows/pipeline.yml - secrets: - AWS_S3_HOST: ${{ secrets.AWS_S3_HOST }} - AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} - AWS_S3_REGION: ${{ secrets.AWS_S3_REGION }} - AWS_S3_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} - AWS_S3_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} - AZURE_CONTAINER_URI: ${{ secrets.AZURE_CONTAINER_URI }} - AZURE_SAS_TOKEN: ${{ secrets.AZURE_SAS_TOKEN }} - GS_BASE_64_ENCODED_PRIVATE_KEY_DATA: ${{ secrets.GS_BASE_64_ENCODED_PRIVATE_KEY_DATA }} - GS_BUCKET: ${{ secrets.GS_BUCKET }} - GS_PROJECT_ID: ${{ secrets.GS_PROJECT_ID }} - MALWARE_SCANNER_URL: ${{ secrets.MALWARE_SCANNER_URL }} - MALWARE_SCANNER_USERNAME: ${{ secrets.MALWARE_SCANNER_USERNAME }} - MALWARE_SCANNER_PASSWORD: ${{ secrets.MALWARE_SCANNER_PASSWORD }} - MALWARE_SCANNER_MTLS_URI: ${{ secrets.MALWARE_SCANNER_MTLS_URI }} - MALWARE_SCANNER_MTLS_CERTIFICATE: ${{ secrets.MALWARE_SCANNER_MTLS_CERTIFICATE }} - MALWARE_SCANNER_MTLS_KEY: ${{ secrets.MALWARE_SCANNER_MTLS_KEY }} - SONARQ_TOKEN: ${{ secrets.SONARQ_TOKEN }} - GH_TOKEN: ${{ secrets.GH_TOKEN }} + secrets: inherit diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index b532e7ca4..72e01eddc 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -1,6 +1,10 @@ name: Reusable Workflow -permissions: read-all +permissions: + actions: read + contents: read + packages: read + security-events: write env: MAVEN_VERSION: '3.9.12' diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 48962c712..1cb329519 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -1,6 +1,10 @@ name: CI - PR -permissions: read-all +permissions: + actions: read + contents: read + packages: read + security-events: write on: workflow_dispatch: @@ -22,22 +26,4 @@ jobs: needs: requires-approval if: always() && (needs.requires-approval.result == 'success' || needs.requires-approval.result == 'skipped') uses: ./.github/workflows/pipeline.yml - secrets: - AWS_S3_HOST: ${{ secrets.AWS_S3_HOST }} - AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} - AWS_S3_REGION: ${{ secrets.AWS_S3_REGION }} - AWS_S3_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} - AWS_S3_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} - AZURE_CONTAINER_URI: ${{ secrets.AZURE_CONTAINER_URI }} - AZURE_SAS_TOKEN: ${{ secrets.AZURE_SAS_TOKEN }} - GS_BASE_64_ENCODED_PRIVATE_KEY_DATA: ${{ secrets.GS_BASE_64_ENCODED_PRIVATE_KEY_DATA }} - GS_BUCKET: ${{ secrets.GS_BUCKET }} - GS_PROJECT_ID: ${{ secrets.GS_PROJECT_ID }} - MALWARE_SCANNER_URL: ${{ secrets.MALWARE_SCANNER_URL }} - MALWARE_SCANNER_USERNAME: ${{ secrets.MALWARE_SCANNER_USERNAME }} - MALWARE_SCANNER_PASSWORD: ${{ secrets.MALWARE_SCANNER_PASSWORD }} - MALWARE_SCANNER_MTLS_URI: ${{ secrets.MALWARE_SCANNER_MTLS_URI }} - MALWARE_SCANNER_MTLS_CERTIFICATE: ${{ secrets.MALWARE_SCANNER_MTLS_CERTIFICATE }} - MALWARE_SCANNER_MTLS_KEY: ${{ secrets.MALWARE_SCANNER_MTLS_KEY }} - SONARQ_TOKEN: ${{ secrets.SONARQ_TOKEN }} - GH_TOKEN: ${{ secrets.GH_TOKEN }} + secrets: inherit From 0ce2515a4ba351b143ce6878b299f62974a05eed Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Mon, 4 May 2026 15:31:09 +0200 Subject: [PATCH 05/21] . --- .github/workflows/main.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 307ffe844..1e19a3d1d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,6 +6,9 @@ permissions: packages: read security-events: write +env: + MAVEN_VERSION: '3.9.12' + on: workflow_dispatch: push: @@ -16,8 +19,6 @@ jobs: name: Blackduck Scan runs-on: ubuntu-latest timeout-minutes: 30 - env: - MAVEN_VERSION: '3.9.12' steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 From 987838e1bf695d6a2693a4adcf7dd67a9e536206 Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Mon, 4 May 2026 15:33:22 +0200 Subject: [PATCH 06/21] make codeql its own action --- .github/actions/scan-with-codeql/action.yml | 40 +++++++++++++++++++++ .github/workflows/pipeline.yml | 23 +++--------- 2 files changed, 44 insertions(+), 19 deletions(-) create mode 100644 .github/actions/scan-with-codeql/action.yml diff --git a/.github/actions/scan-with-codeql/action.yml b/.github/actions/scan-with-codeql/action.yml new file mode 100644 index 000000000..7c22ba7c8 --- /dev/null +++ b/.github/actions/scan-with-codeql/action.yml @@ -0,0 +1,40 @@ +name: CodeQL Analysis +description: Runs CodeQL security analysis on the project. + +inputs: + java-version: + description: The Java version to use for the build. + required: true + maven-version: + description: The Maven version to use for the build. + required: true + +runs: + using: composite + steps: + - name: Set up Java ${{ inputs.java-version }} + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: ${{ inputs.java-version }} + distribution: sapmachine + cache: maven + + - name: Set up Maven ${{ inputs.maven-version }} + uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5 + with: + maven-version: ${{ inputs.maven-version }} + + - name: Initialize CodeQL + uses: github/codeql-action/init@ed410739ba306e4ebe5e123421a6bd694e494a2b # v4 + with: + languages: java-kotlin + build-mode: manual + + - name: Build Java code + run: mvn clean compile -DskipTests -B -ntp + shell: bash + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@ed410739ba306e4ebe5e123421a6bd694e494a2b # v4 + with: + category: "/language:java-kotlin" diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 72e01eddc..2fc87919b 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -166,23 +166,8 @@ jobs: with: ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} - - name: Set up Java - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 - with: - java-version: '17' - distribution: 'sapmachine' - cache: 'maven' - - - name: Initialize CodeQL - uses: github/codeql-action/init@ed410739ba306e4ebe5e123421a6bd694e494a2b # v4 + - name: CodeQL Analysis + uses: ./.github/actions/scan-with-codeql with: - languages: java-kotlin - build-mode: manual - - - name: Build Java code - run: mvn clean compile -DskipTests -B -ntp - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ed410739ba306e4ebe5e123421a6bd694e494a2b # v4 - with: - category: "/language:java-kotlin" + java-version: 17 + maven-version: ${{ env.MAVEN_VERSION }} From 4767d3c00ab3c7b23abd36693031a3dc8a367ebb Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Mon, 4 May 2026 15:36:00 +0200 Subject: [PATCH 07/21] simplify --- .github/actions/scan-with-codeql/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/scan-with-codeql/action.yml b/.github/actions/scan-with-codeql/action.yml index 7c22ba7c8..4be2598e3 100644 --- a/.github/actions/scan-with-codeql/action.yml +++ b/.github/actions/scan-with-codeql/action.yml @@ -31,7 +31,7 @@ runs: build-mode: manual - name: Build Java code - run: mvn clean compile -DskipTests -B -ntp + run: mvn clean compile -B -ntp shell: bash - name: Perform CodeQL Analysis From cbcc5da888cf3eb69cdcd76e0b718cdcebd4a69a Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Mon, 4 May 2026 15:37:40 +0200 Subject: [PATCH 08/21] simplify v2 --- .github/workflows/pipeline.yml | 37 ---------------------------------- 1 file changed, 37 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 2fc87919b..e36236383 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -11,43 +11,6 @@ env: on: workflow_call: - secrets: - AWS_S3_HOST: - required: true - AWS_S3_BUCKET: - required: true - AWS_S3_REGION: - required: true - AWS_S3_ACCESS_KEY_ID: - required: true - AWS_S3_SECRET_ACCESS_KEY: - required: true - AZURE_CONTAINER_URI: - required: true - AZURE_SAS_TOKEN: - required: true - GS_BASE_64_ENCODED_PRIVATE_KEY_DATA: - required: true - GS_BUCKET: - required: true - GS_PROJECT_ID: - required: true - MALWARE_SCANNER_URL: - required: true - MALWARE_SCANNER_USERNAME: - required: true - MALWARE_SCANNER_PASSWORD: - required: true - MALWARE_SCANNER_MTLS_URI: - required: true - MALWARE_SCANNER_MTLS_CERTIFICATE: - required: true - MALWARE_SCANNER_MTLS_KEY: - required: true - SONARQ_TOKEN: - required: true - GH_TOKEN: - required: true jobs: spotless: From d38d6fc618f22bebc169c0af92659aaccb32221d Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Mon, 4 May 2026 15:50:05 +0200 Subject: [PATCH 09/21] remove pitest --- CLAUDE.md | 1 - cds-feature-attachments/pom.xml | 34 --------------------------------- doc/Design.md | 22 +++------------------ pom.xml | 5 ----- 4 files changed, 3 insertions(+), 59 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 49cf9e133..22734dc62 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -122,7 +122,6 @@ Defined in `cds-feature-attachments/src/main/resources/cds/com.sap.cds/cds-featu All enforced in CI: - **JaCoCo:** 95% minimum (instruction, branch, complexity), 0 missed classes -- **Mutation testing (Pitest):** 90% aggregated threshold on `handler.*` and `service.*` - **SpotBugs:** max effort, includes tests - **PMD:** SAP Cloud SDK rules, excludes generated code and tests - **Spotless:** Google Java Format check diff --git a/cds-feature-attachments/pom.xml b/cds-feature-attachments/pom.xml index 44bec84e4..dda78a2d7 100644 --- a/cds-feature-attachments/pom.xml +++ b/cds-feature-attachments/pom.xml @@ -92,40 +92,6 @@ ${project.artifactId} - - org.pitest - pitest-maven - - - com.sap.cds.feature.attachments.handler.* - com.sap.cds.feature.attachments.service.* - - - CONSTRUCTOR_CALLS - VOID_METHOD_CALLS - NON_VOID_METHOD_CALLS - REMOVE_CONDITIONALS_ORDER_ELSE - CONDITIONALS_BOUNDARY - EMPTY_RETURNS - NEGATE_CONDITIONALS - REMOVE_CONDITIONALS_EQUAL_IF - REMOVE_CONDITIONALS_EQUAL_ELSE - REMOVE_CONDITIONALS_ORDER_IF - REMOVE_CONDITIONALS_ORDER_ELSE - - 95 - 90 - - - - - org.pitest - pitest-junit5-plugin - 1.2.3 - - - - maven-clean-plugin diff --git a/doc/Design.md b/doc/Design.md index 1945024c5..6777dde22 100644 --- a/doc/Design.md +++ b/doc/Design.md @@ -51,7 +51,6 @@ - [Texts](#texts) - [Tests](#tests) - [Unit Tests](#unit-tests) - - [Mutation Tests](#mutation-tests) - [Integration Tests](#integration-tests) - [Quality Tools](#quality-tools) @@ -93,21 +92,19 @@ In folder `.github/workflows` are the GitHub Actions defined. The following tabl | File Name | Description | | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `pr.yml` | Builds and tests pull requests for Java 17 and 21. Requires approval for external forks. Each pull request needs green runs from this workflow to be merged. | -| `main.yml` | Builds, tests, and deploys snapshots when commits are merged to main. Runs unit tests, integration tests, and mutation tests for Java 17 and 21. | +| `main.yml` | Builds and tests when commits are merged to main. Runs unit tests and integration tests for Java 17 and 21. | | `release.yml` | Triggered on GitHub releases. Updates version, runs BlackDuck scan, builds, tests, and deploys to Maven Central. See also [Build and Deploy](#build-and-deploy). | | `pipeline.yml` | Reusable workflow containing shared build, test, integration test, SonarQube scan, CodeQL analysis, and snapshot deployment logic. Called by `pr.yml` and `main.yml`. | ### Build Action The build step is implemented in action `.github/actions/build/action.yml` which is used in the workflows via `pipeline.yml`. -As the build action does not only run a build of the project, but also the mutation tests, this action is used in all -the mentioned workflows. Additional reusable actions are defined in `.github/actions/`: | Action | Description | | --------------------- | ----------------------------------------------------------- | -| `build` | Builds the project and runs unit/mutation tests | +| `build` | Builds the project and runs unit tests | | `integration-tests` | Runs integration tests (build-version, latest-version, oss) | | `deploy-release` | Deploys release artifacts to Maven Central | | `newrelease` | Updates version in pom.xml for new releases | @@ -142,7 +139,7 @@ The following steps are executed in the workflow: 1. Update the version in the `pom.xml` files. The tag used in the release is read and git commands are used to update the property `revision` in the parent `pom.xml` file. -2. Build the project and run all unit, integration and mutation tests. Here a reuse action is used which is also +2. Build the project and run all unit and integration tests. Here a reuse action is used which is also executed in the main and pull request build. 3. Deploy the project to maven or artifactory. The deployment is done with the maven command `mvn deploy`. The deployment is done to the repository defined in the `pom.xml` file. So only project parts which have defined the @@ -660,18 +657,6 @@ The following settings are used for this plugin: | Complexity Coverage | 95% | | Class Missed Count | 0 | -#### Mutation Tests - -In addition to this plugin, also mutation tests are executed during the build of the project in the GitHub Actions. -To run the mutation tests the plugin `pitest-maven` is included in the same pom. - -Several mutators are maintained in the plugin and the following settings are used: - -| Setting | Value | -| ----------------------------- | ----- | -| Coverage Threshold | 95% | -| Aggregated Mutation Threshold | 90% | - ### Integration Tests Spring Boot tests are implemented in the `integration-tests` folder. @@ -746,7 +731,6 @@ The following quality tools are used in the project to ensure the quality of the | Spotbugs | Defined in the root `pom.xml` | Static Code check for Java code working in the bytecode. | | PMD/CPD | Defined in the root `pom.xml` | Static Code check for Java code working on the source code. CPD checks the coding for duplications. | | Maven Enforcer Plugin | Defined in the root `pom.xml` | Checks if there are dependencies declared twice. | -| Mutation Tests | Defined in `cds-feature-attachments/pom.xml` | See section [mutation tests](#mutation-tests). | | Jacoco | Defined in `cds-feature-attachments/pom.xml` | See section [unit tests](#unit-tests). | | Dependabot | Config is defined in the `.github/dependabot.yml` | Checks for new versions of dependencies. | | CodeQL | Defined in `pipeline.yml` | Checks for vulnerabilities in the coding. Executed as part of the CI pipeline. | diff --git a/pom.xml b/pom.xml index 2e775ac3b..024fe7d44 100644 --- a/pom.xml +++ b/pom.xml @@ -238,11 +238,6 @@ jacoco-maven-plugin 0.8.14 - - org.pitest - pitest-maven - 1.23.0 - com.github.spotbugs spotbugs-maven-plugin From 719bdb7bbef38ab1c81b1a24977a9e3f8a381005 Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Tue, 5 May 2026 10:02:53 +0200 Subject: [PATCH 10/21] update actions --- .github/actions/cf-bind/action.yml | 78 +++++++++++++++++++ .github/actions/integration-tests/action.yml | 27 ++----- .github/actions/scan-with-sonar/action.yml | 2 +- .github/workflows/pipeline.yml | 60 ++++++-------- .../malware/client/MalwareScanClientIT.java | 58 ++++---------- .../mt/oss/AwsMtxOssStorageTest.java | 38 ++------- .../mt/oss/AzureMtxOssStorageTest.java | 28 ++----- .../mt/oss/GcpMtxOssStorageTest.java | 31 ++------ pom.xml | 10 +-- .../attachments/oss/client/AWSClientIT.java | 41 +++------- .../attachments/oss/client/AzureClientIT.java | 31 +++----- .../oss/client/GoogleClientIT.java | 34 +++----- 12 files changed, 181 insertions(+), 257 deletions(-) create mode 100644 .github/actions/cf-bind/action.yml diff --git a/.github/actions/cf-bind/action.yml b/.github/actions/cf-bind/action.yml new file mode 100644 index 000000000..08ce16dbd --- /dev/null +++ b/.github/actions/cf-bind/action.yml @@ -0,0 +1,78 @@ +name: Bind Cloud Foundry Services +description: Login to CF and bind services for hybrid testing via cds bind + +inputs: + cf-api: + description: Cloud Foundry API endpoint + required: true + cf-username: + description: Cloud Foundry username + required: true + cf-password: + description: Cloud Foundry password + required: true + cf-org: + description: Cloud Foundry organization + required: true + cf-space: + description: Cloud Foundry space + required: true + auth-method: + description: 'Malware scanner authentication method: basic or mtls' + required: true + +runs: + using: composite + steps: + - name: Install CF CLI + shell: bash + run: | + wget -q "https://packages.cloudfoundry.org/stable?release=linux64-binary&version=8.9.0&source=github-rel" -O cf-cli.tar.gz + tar -xzf cf-cli.tar.gz + sudo mv cf8 /usr/local/bin/cf + cf --version + + - name: CF Login + shell: bash + run: | + for i in {1..5}; do + cf login -a ${{ inputs.cf-api }} -u ${{ inputs.cf-username }} \ + -p ${{ inputs.cf-password }} -o ${{ inputs.cf-org }} -s ${{ inputs.cf-space }} && break + echo "cf login failed, retrying ($i/5)..." + sleep 10 + if [ "$i" -eq 5 ]; then + echo "cf login failed after 5 attempts." + exit 1 + fi + done + + - name: Install CDS dependencies + shell: bash + run: npm ci + working-directory: integration-tests/mtx-local + + - name: Bind objectstore + shell: bash + working-directory: integration-tests/mtx-local + run: | + for i in {1..5}; do + npx cds bind os -2 os:pipeline && break + echo "cds bind objectstore failed, retrying ($i/5)..." + sleep 30 + if [ "$i" -eq 5 ]; then + echo "cds bind objectstore failed after 5 attempts." + exit 1 + fi + done + + - name: Bind malware-scanner (basic) + if: inputs.auth-method == 'basic' + shell: bash + working-directory: integration-tests/mtx-local + run: npx cds bind malware -2 malware:malware-key-basic + + - name: Bind malware-scanner (mtls) + if: inputs.auth-method == 'mtls' + shell: bash + working-directory: integration-tests/mtx-local + run: npx cds bind malware -2 malware:malware-key-mtls diff --git a/.github/actions/integration-tests/action.yml b/.github/actions/integration-tests/action.yml index 8be8de2ab..0b19579f0 100644 --- a/.github/actions/integration-tests/action.yml +++ b/.github/actions/integration-tests/action.yml @@ -1,5 +1,5 @@ -name: Integration Tests with current version of CAP Java -description: Run integration tests with the current version of CAP Java using Maven. +name: Integration Tests +description: Run integration tests using Maven with cds bind for service bindings. inputs: java-version: @@ -8,12 +8,6 @@ inputs: maven-version: description: The Maven version the build shall run with. required: true - test-type: - description: 'Which integration test to run: build-version, latest-version, or oss' - required: true - auth-method: - description: 'Authentication method: basic or mtls' - required: true runs: using: composite @@ -34,17 +28,12 @@ runs: run: mvn clean install -ntp -B -pl cds-feature-attachments,storage-targets/cds-feature-attachments-fs,storage-targets/cds-feature-attachments-oss -am shell: bash - - name: Integration Tests with version of CAP Java used for build - if: inputs.test-type == 'build-version' - run: mvn clean verify -ntp -B -f ./integration-tests/pom.xml - shell: bash - - - name: Integration Tests with latest version of CAP Java - if: inputs.test-type == 'latest-version' - run: mvn clean verify -ntp -B -f ./integration-tests/pom.xml -P latest-test-version + - name: Integration Tests (build version) + run: npx cds bind --exec -- mvn clean verify -ntp -B -f ../../integration-tests/pom.xml + working-directory: integration-tests/mtx-local shell: bash - - name: Integration Tests for the object store service - if: inputs.test-type == 'oss' - run: mvn clean verify -ntp -B -Pintegration-tests-oss + - name: Integration Tests (latest CAP Java) + run: npx cds bind --exec -- mvn verify -ntp -B -f ../../integration-tests/pom.xml -P latest-test-version + working-directory: integration-tests/mtx-local shell: bash diff --git a/.github/actions/scan-with-sonar/action.yml b/.github/actions/scan-with-sonar/action.yml index a39d76125..0258878d2 100644 --- a/.github/actions/scan-with-sonar/action.yml +++ b/.github/actions/scan-with-sonar/action.yml @@ -71,7 +71,7 @@ runs: -Dsonar.qualitygate.wait=true -Dsonar.java.source=17 -Dsonar.exclusions=**/samples/** - -Dsonar.coverage.jacoco.xmlReportPaths=coverage-report/target/site/jacoco-aggregate/jacoco.xml + -Dsonar.coverage.jacoco.xmlReportPaths=${{ github.workspace }}/coverage-report/target/site/jacoco-aggregate/jacoco.xml -Dsonar.coverage.exclusions=cds-feature-attachments/src/test/**,cds-feature-attachments/src/gen/**,storage-targets/cds-feature-attachments-fs/src/test/**,storage-targets/cds-feature-attachments-oss/src/test/** -B -ntp shell: bash diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index e36236383..10e74fcf4 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -39,73 +39,57 @@ jobs: run: mvn spotless:check -Dspotless.check.skip=false -B -ntp integration-tests: - name: ITests (Java ${{ matrix.java-version }}, ${{ matrix.test-type }}, ${{ matrix.auth-method }}) + name: ITests (Java ${{ matrix.java-version }}, ${{ matrix.auth-method }}, ${{ matrix.hyperscaler }}) runs-on: ubuntu-latest timeout-minutes: 30 strategy: fail-fast: false matrix: java-version: [ 17, 21 ] - test-type: [ build-version, latest-version, oss ] auth-method: [ basic, mtls ] - env: - AWS_S3_HOST: ${{ secrets.AWS_S3_HOST }} - AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} - AWS_S3_REGION: ${{ secrets.AWS_S3_REGION }} - AWS_S3_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} - AWS_S3_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} - AZURE_CONTAINER_URI: ${{ secrets.AZURE_CONTAINER_URI }} - AZURE_SAS_TOKEN: ${{ secrets.AZURE_SAS_TOKEN }} - GS_BASE_64_ENCODED_PRIVATE_KEY_DATA: ${{ secrets.GS_BASE_64_ENCODED_PRIVATE_KEY_DATA }} - GS_BUCKET: ${{ secrets.GS_BUCKET }} - GS_PROJECT_ID: ${{ secrets.GS_PROJECT_ID }} - MALWARE_SCANNER_URL: ${{ matrix.auth-method == 'basic' && secrets.MALWARE_SCANNER_URL || '' }} - MALWARE_SCANNER_USERNAME: ${{ matrix.auth-method == 'basic' && secrets.MALWARE_SCANNER_USERNAME || '' }} - MALWARE_SCANNER_PASSWORD: ${{ matrix.auth-method == 'basic' && secrets.MALWARE_SCANNER_PASSWORD || '' }} - MALWARE_SCANNER_MTLS_URI: ${{ matrix.auth-method == 'mtls' && secrets.MALWARE_SCANNER_MTLS_URI || '' }} - MALWARE_SCANNER_MTLS_CERTIFICATE: ${{ matrix.auth-method == 'mtls' && secrets.MALWARE_SCANNER_MTLS_CERTIFICATE || '' }} - MALWARE_SCANNER_MTLS_KEY: ${{ matrix.auth-method == 'mtls' && secrets.MALWARE_SCANNER_MTLS_KEY || '' }} + hyperscaler: [ AWS, AZURE, GCP ] steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} + - name: Bind CF Services + uses: ./.github/actions/cf-bind + with: + cf-api: ${{ secrets[format('CF_API_{0}', matrix.hyperscaler)] }} + cf-username: ${{ secrets.CF_USERNAME }} + cf-password: ${{ secrets.CF_PASSWORD }} + cf-org: ${{ secrets[format('CF_ORG_{0}', matrix.hyperscaler)] }} + cf-space: ${{ secrets[format('CF_SPACE_{0}', matrix.hyperscaler)] }} + auth-method: ${{ matrix.auth-method }} + - name: Integration Tests uses: ./.github/actions/integration-tests with: java-version: ${{ matrix.java-version }} maven-version: ${{ env.MAVEN_VERSION }} - test-type: ${{ matrix.test-type }} - auth-method: ${{ matrix.auth-method }} sonarqube-scan: name: SonarQube Scan runs-on: ubuntu-latest timeout-minutes: 30 - env: - AWS_S3_HOST: ${{ secrets.AWS_S3_HOST }} - AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} - AWS_S3_REGION: ${{ secrets.AWS_S3_REGION }} - AWS_S3_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} - AWS_S3_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} - AZURE_CONTAINER_URI: ${{ secrets.AZURE_CONTAINER_URI }} - AZURE_SAS_TOKEN: ${{ secrets.AZURE_SAS_TOKEN }} - GS_BASE_64_ENCODED_PRIVATE_KEY_DATA: ${{ secrets.GS_BASE_64_ENCODED_PRIVATE_KEY_DATA }} - GS_BUCKET: ${{ secrets.GS_BUCKET }} - GS_PROJECT_ID: ${{ secrets.GS_PROJECT_ID }} - MALWARE_SCANNER_URL: ${{ secrets.MALWARE_SCANNER_URL }} - MALWARE_SCANNER_USERNAME: ${{ secrets.MALWARE_SCANNER_USERNAME }} - MALWARE_SCANNER_PASSWORD: ${{ secrets.MALWARE_SCANNER_PASSWORD }} - MALWARE_SCANNER_MTLS_URI: ${{ secrets.MALWARE_SCANNER_MTLS_URI }} - MALWARE_SCANNER_MTLS_CERTIFICATE: ${{ secrets.MALWARE_SCANNER_MTLS_CERTIFICATE }} - MALWARE_SCANNER_MTLS_KEY: ${{ secrets.MALWARE_SCANNER_MTLS_KEY }} steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} + - name: Bind CF Services + uses: ./.github/actions/cf-bind + with: + cf-api: ${{ secrets.CF_API_AWS }} + cf-username: ${{ secrets.CF_USERNAME }} + cf-password: ${{ secrets.CF_PASSWORD }} + cf-org: ${{ secrets.CF_ORG_AWS }} + cf-space: ${{ secrets.CF_SPACE_AWS }} + auth-method: basic + - name: SonarQube Scan uses: ./.github/actions/scan-with-sonar with: diff --git a/cds-feature-attachments/src/test/java/com/sap/cds/feature/attachments/service/malware/client/MalwareScanClientIT.java b/cds-feature-attachments/src/test/java/com/sap/cds/feature/attachments/service/malware/client/MalwareScanClientIT.java index e29302c74..b1d247a84 100644 --- a/cds-feature-attachments/src/test/java/com/sap/cds/feature/attachments/service/malware/client/MalwareScanClientIT.java +++ b/cds-feature-attachments/src/test/java/com/sap/cds/feature/attachments/service/malware/client/MalwareScanClientIT.java @@ -4,15 +4,13 @@ package com.sap.cds.feature.attachments.service.malware.client; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; import com.sap.cds.services.environment.CdsProperties.ConnectionPool; +import com.sap.cloud.environment.servicebinding.api.DefaultServiceBindingAccessor; import com.sap.cloud.environment.servicebinding.api.ServiceBinding; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; import java.time.Duration; -import java.util.Map; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Nested; @@ -20,9 +18,6 @@ import org.junit.jupiter.api.TestInstance; class MalwareScanClientIT { - // The tests in this class are intended to run against a real Malware Scanner instance. - // They require valid credentials set up in the environment. - // Basic auth and mTLS tests skip independently when their credentials are missing. private static final String EICAR_TEST_STRING = "X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*"; @@ -30,15 +25,16 @@ class MalwareScanClientIT { private static final ConnectionPool CONNECTION_POOL = new ConnectionPool(Duration.ofSeconds(120), 20, 20); - private static MalwareScanClient buildClient(Map creds) { - ServiceBinding binding = mock(ServiceBinding.class); - when(binding.getCredentials()).thenReturn(creds); - HttpClientProvider clientProvider = new MalwareScanClientProvider(binding, CONNECTION_POOL); - return new DefaultMalwareScanClient(clientProvider); + private static ServiceBinding getMalwareScannerBinding() { + return DefaultServiceBindingAccessor.getInstance().getServiceBindings().stream() + .filter(b -> b.getServiceName().map("malware-scanner"::equals).orElse(false)) + .findFirst() + .orElse(null); } - private static String normalizePem(String pem) { - return pem.replace("\\n", "\n"); + private static MalwareScanClient buildClient(ServiceBinding binding) { + HttpClientProvider clientProvider = new MalwareScanClientProvider(binding, CONNECTION_POOL); + return new DefaultMalwareScanClient(clientProvider); } @Nested @@ -49,18 +45,12 @@ class BasicAuth { @BeforeAll void setUp() { - String url = System.getenv("MALWARE_SCANNER_URL"); - String username = System.getenv("MALWARE_SCANNER_USERNAME"); - String password = System.getenv("MALWARE_SCANNER_PASSWORD"); - - if (url == null || username == null || password == null) { - client = null; - } else { - client = buildClient(Map.of("url", url, "username", username, "password", password)); + ServiceBinding binding = getMalwareScannerBinding(); + if (binding != null && binding.getCredentials().containsKey("username")) { + client = buildClient(binding); } - Assumptions.assumeTrue( - client != null, "Basic auth malware scanner credentials not available — skipping tests"); + client != null, "Basic auth malware scanner binding not available — skipping tests"); } @Test @@ -90,26 +80,12 @@ class Mtls { @BeforeAll void setUp() { - String uri = System.getenv("MALWARE_SCANNER_MTLS_URI"); - String certificate = System.getenv("MALWARE_SCANNER_MTLS_CERTIFICATE"); - String key = System.getenv("MALWARE_SCANNER_MTLS_KEY"); - - if (uri == null || certificate == null || key == null) { - client = null; - } else { - client = - buildClient( - Map.of( - "uri", - uri, - "certificate", - normalizePem(certificate), - "key", - normalizePem(key))); + ServiceBinding binding = getMalwareScannerBinding(); + if (binding != null && binding.getCredentials().containsKey("certificate")) { + client = buildClient(binding); } - Assumptions.assumeTrue( - client != null, "mTLS malware scanner credentials not available — skipping tests"); + client != null, "mTLS malware scanner binding not available — skipping tests"); } @Test diff --git a/integration-tests/mtx-local/srv/src/test/java/com/sap/cds/feature/attachments/integrationtests/mt/oss/AwsMtxOssStorageTest.java b/integration-tests/mtx-local/srv/src/test/java/com/sap/cds/feature/attachments/integrationtests/mt/oss/AwsMtxOssStorageTest.java index 068504f6e..c2e8d5710 100644 --- a/integration-tests/mtx-local/srv/src/test/java/com/sap/cds/feature/attachments/integrationtests/mt/oss/AwsMtxOssStorageTest.java +++ b/integration-tests/mtx-local/srv/src/test/java/com/sap/cds/feature/attachments/integrationtests/mt/oss/AwsMtxOssStorageTest.java @@ -3,46 +3,22 @@ */ package com.sap.cds.feature.attachments.integrationtests.mt.oss; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - +import com.sap.cloud.environment.servicebinding.api.DefaultServiceBindingAccessor; import com.sap.cloud.environment.servicebinding.api.ServiceBinding; -import java.util.HashMap; /** * Runs the multitenancy OSS storage integration tests against a real AWS S3 instance. Skipped - * automatically if the required environment variables are not set. - * - *

Required environment variables: {@code AWS_S3_HOST}, {@code AWS_S3_BUCKET}, {@code - * AWS_S3_REGION}, {@code AWS_S3_ACCESS_KEY_ID}, {@code AWS_S3_SECRET_ACCESS_KEY}. + * automatically if no objectstore binding with AWS credentials is available in VCAP_SERVICES. */ class AwsMtxOssStorageTest extends AbstractMtxOssStorageTest { @Override protected ServiceBinding getServiceBinding() { - String host = System.getenv("AWS_S3_HOST"); - String bucket = System.getenv("AWS_S3_BUCKET"); - String region = System.getenv("AWS_S3_REGION"); - String accessKeyId = System.getenv("AWS_S3_ACCESS_KEY_ID"); - String secretAccessKey = System.getenv("AWS_S3_SECRET_ACCESS_KEY"); - - if (host == null - || bucket == null - || region == null - || accessKeyId == null - || secretAccessKey == null) { - return null; - } - - ServiceBinding binding = mock(ServiceBinding.class); - HashMap creds = new HashMap<>(); - creds.put("host", host); - creds.put("bucket", bucket); - creds.put("region", region); - creds.put("access_key_id", accessKeyId); - creds.put("secret_access_key", secretAccessKey); - when(binding.getCredentials()).thenReturn(creds); - return binding; + return DefaultServiceBindingAccessor.getInstance().getServiceBindings().stream() + .filter(b -> b.getServiceName().map("objectstore"::equals).orElse(false)) + .filter(b -> b.getCredentials().containsKey("access_key_id")) + .findFirst() + .orElse(null); } @Override diff --git a/integration-tests/mtx-local/srv/src/test/java/com/sap/cds/feature/attachments/integrationtests/mt/oss/AzureMtxOssStorageTest.java b/integration-tests/mtx-local/srv/src/test/java/com/sap/cds/feature/attachments/integrationtests/mt/oss/AzureMtxOssStorageTest.java index 1ebe1a354..f806406be 100644 --- a/integration-tests/mtx-local/srv/src/test/java/com/sap/cds/feature/attachments/integrationtests/mt/oss/AzureMtxOssStorageTest.java +++ b/integration-tests/mtx-local/srv/src/test/java/com/sap/cds/feature/attachments/integrationtests/mt/oss/AzureMtxOssStorageTest.java @@ -3,35 +3,23 @@ */ package com.sap.cds.feature.attachments.integrationtests.mt.oss; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - +import com.sap.cloud.environment.servicebinding.api.DefaultServiceBindingAccessor; import com.sap.cloud.environment.servicebinding.api.ServiceBinding; -import java.util.HashMap; /** * Runs the multitenancy OSS storage integration tests against a real Azure Blob Storage instance. - * Skipped automatically if the required environment variables are not set. - * - *

Required environment variables: {@code AZURE_CONTAINER_URI}, {@code AZURE_SAS_TOKEN}. + * Skipped automatically if no objectstore binding with Azure credentials is available in + * VCAP_SERVICES. */ class AzureMtxOssStorageTest extends AbstractMtxOssStorageTest { @Override protected ServiceBinding getServiceBinding() { - String containerUri = System.getenv("AZURE_CONTAINER_URI"); - String sasToken = System.getenv("AZURE_SAS_TOKEN"); - - if (containerUri == null || sasToken == null) { - return null; - } - - ServiceBinding binding = mock(ServiceBinding.class); - HashMap creds = new HashMap<>(); - creds.put("container_uri", containerUri); - creds.put("sas_token", sasToken); - when(binding.getCredentials()).thenReturn(creds); - return binding; + return DefaultServiceBindingAccessor.getInstance().getServiceBindings().stream() + .filter(b -> b.getServiceName().map("objectstore"::equals).orElse(false)) + .filter(b -> b.getCredentials().containsKey("container_uri")) + .findFirst() + .orElse(null); } @Override diff --git a/integration-tests/mtx-local/srv/src/test/java/com/sap/cds/feature/attachments/integrationtests/mt/oss/GcpMtxOssStorageTest.java b/integration-tests/mtx-local/srv/src/test/java/com/sap/cds/feature/attachments/integrationtests/mt/oss/GcpMtxOssStorageTest.java index 017248d77..9476ff780 100644 --- a/integration-tests/mtx-local/srv/src/test/java/com/sap/cds/feature/attachments/integrationtests/mt/oss/GcpMtxOssStorageTest.java +++ b/integration-tests/mtx-local/srv/src/test/java/com/sap/cds/feature/attachments/integrationtests/mt/oss/GcpMtxOssStorageTest.java @@ -3,38 +3,23 @@ */ package com.sap.cds.feature.attachments.integrationtests.mt.oss; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - +import com.sap.cloud.environment.servicebinding.api.DefaultServiceBindingAccessor; import com.sap.cloud.environment.servicebinding.api.ServiceBinding; -import java.util.HashMap; /** * Runs the multitenancy OSS storage integration tests against a real Google Cloud Storage instance. - * Skipped automatically if the required environment variables are not set. - * - *

Required environment variables: {@code GS_BUCKET}, {@code GS_PROJECT_ID}, {@code - * GS_BASE_64_ENCODED_PRIVATE_KEY_DATA}. + * Skipped automatically if no objectstore binding with GCP credentials is available in + * VCAP_SERVICES. */ class GcpMtxOssStorageTest extends AbstractMtxOssStorageTest { @Override protected ServiceBinding getServiceBinding() { - String bucket = System.getenv("GS_BUCKET"); - String projectId = System.getenv("GS_PROJECT_ID"); - String base64EncodedPrivateKeyData = System.getenv("GS_BASE_64_ENCODED_PRIVATE_KEY_DATA"); - - if (bucket == null || projectId == null || base64EncodedPrivateKeyData == null) { - return null; - } - - ServiceBinding binding = mock(ServiceBinding.class); - HashMap creds = new HashMap<>(); - creds.put("bucket", bucket); - creds.put("projectId", projectId); - creds.put("base64EncodedPrivateKeyData", base64EncodedPrivateKeyData); - when(binding.getCredentials()).thenReturn(creds); - return binding; + return DefaultServiceBindingAccessor.getInstance().getServiceBindings().stream() + .filter(b -> b.getServiceName().map("objectstore"::equals).orElse(false)) + .filter(b -> b.getCredentials().containsKey("base64EncodedPrivateKeyData")) + .findFirst() + .orElse(null); } @Override diff --git a/pom.xml b/pom.xml index 024fe7d44..78fc4a81b 100644 --- a/pom.xml +++ b/pom.xml @@ -69,15 +69,9 @@ 2.42.33 0.44.0 - - - 4.6.1 - - 9.6.1 - - 4.8.0 - 9.7.2 + 4.9.0 + 9.9.0 true diff --git a/storage-targets/cds-feature-attachments-oss/src/test/java/com/sap/cds/feature/attachments/oss/client/AWSClientIT.java b/storage-targets/cds-feature-attachments-oss/src/test/java/com/sap/cds/feature/attachments/oss/client/AWSClientIT.java index 40aef4d38..d40a3c354 100644 --- a/storage-targets/cds-feature-attachments-oss/src/test/java/com/sap/cds/feature/attachments/oss/client/AWSClientIT.java +++ b/storage-targets/cds-feature-attachments-oss/src/test/java/com/sap/cds/feature/attachments/oss/client/AWSClientIT.java @@ -3,51 +3,30 @@ */ package com.sap.cds.feature.attachments.oss.client; -import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assumptions.assumeTrue; import com.sap.cds.feature.attachments.oss.handler.OSSAttachmentsServiceHandlerTestUtils; +import com.sap.cloud.environment.servicebinding.api.DefaultServiceBindingAccessor; import com.sap.cloud.environment.servicebinding.api.ServiceBinding; -import java.util.HashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.junit.jupiter.api.Test; class AWSClientIT { - // The tests in this class are intended to run against a real AWS Storage instance. - // They require a valid ServiceBinding with credentials set up in the environment. @Test void testCreateReadDeleteAttachmentFlowAWS() { - ServiceBinding binding = getRealServiceBindingAWS(); + ServiceBinding binding = getObjectStoreBinding(); + assumeTrue(binding != null, "No AWS objectstore binding available"); ExecutorService executor = Executors.newCachedThreadPool(); OSSAttachmentsServiceHandlerTestUtils.testCreateReadDeleteAttachmentFlow(binding, executor); } - private ServiceBinding getRealServiceBindingAWS() { - // Read environment variables - String host = System.getenv("AWS_S3_HOST"); - String bucket = System.getenv("AWS_S3_BUCKET"); - String region = System.getenv("AWS_S3_REGION"); - String accessKeyId = System.getenv("AWS_S3_ACCESS_KEY_ID"); - String secretAccessKey = System.getenv("AWS_S3_SECRET_ACCESS_KEY"); - - // Return null if any are missing - if (host == null - || bucket == null - || region == null - || accessKeyId == null - || secretAccessKey == null) { - return null; - } - - ServiceBinding binding = mock(ServiceBinding.class); - HashMap creds = new HashMap<>(); - creds.put("host", host); - creds.put("bucket", bucket); - creds.put("region", region); - creds.put("access_key_id", accessKeyId); - creds.put("secret_access_key", secretAccessKey); - when(binding.getCredentials()).thenReturn(creds); - return binding; + private ServiceBinding getObjectStoreBinding() { + return DefaultServiceBindingAccessor.getInstance().getServiceBindings().stream() + .filter(b -> b.getServiceName().map("objectstore"::equals).orElse(false)) + .filter(b -> b.getCredentials().containsKey("access_key_id")) + .findFirst() + .orElse(null); } } diff --git a/storage-targets/cds-feature-attachments-oss/src/test/java/com/sap/cds/feature/attachments/oss/client/AzureClientIT.java b/storage-targets/cds-feature-attachments-oss/src/test/java/com/sap/cds/feature/attachments/oss/client/AzureClientIT.java index 387e6b683..fc16a1fbe 100644 --- a/storage-targets/cds-feature-attachments-oss/src/test/java/com/sap/cds/feature/attachments/oss/client/AzureClientIT.java +++ b/storage-targets/cds-feature-attachments-oss/src/test/java/com/sap/cds/feature/attachments/oss/client/AzureClientIT.java @@ -3,41 +3,30 @@ */ package com.sap.cds.feature.attachments.oss.client; -import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assumptions.assumeTrue; import com.sap.cds.feature.attachments.oss.handler.OSSAttachmentsServiceHandlerTestUtils; +import com.sap.cloud.environment.servicebinding.api.DefaultServiceBindingAccessor; import com.sap.cloud.environment.servicebinding.api.ServiceBinding; -import java.util.HashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.junit.jupiter.api.Test; class AzureClientIT { - // The tests in this class are intended to run against a real Azure instance. - // They require a valid ServiceBinding with credentials set up in the environment. @Test void testCreateReadDeleteAttachmentFlowAzure() { - ServiceBinding binding = getRealServiceBindingAzure(); + ServiceBinding binding = getObjectStoreBinding(); + assumeTrue(binding != null, "No Azure objectstore binding available"); ExecutorService executor = Executors.newCachedThreadPool(); - OSSAttachmentsServiceHandlerTestUtils.testCreateReadDeleteAttachmentFlow(binding, executor); } - private ServiceBinding getRealServiceBindingAzure() { - // Read environment variables - String containerUri = System.getenv("AZURE_CONTAINER_URI"); - String sasToken = System.getenv("AZURE_SAS_TOKEN"); - // Return null if any are missing - if (containerUri == null || sasToken == null) { - return null; - } - - ServiceBinding binding = mock(ServiceBinding.class); - HashMap creds = new HashMap<>(); - creds.put("container_uri", containerUri); - creds.put("sas_token", sasToken); - when(binding.getCredentials()).thenReturn(creds); - return binding; + private ServiceBinding getObjectStoreBinding() { + return DefaultServiceBindingAccessor.getInstance().getServiceBindings().stream() + .filter(b -> b.getServiceName().map("objectstore"::equals).orElse(false)) + .filter(b -> b.getCredentials().containsKey("container_uri")) + .findFirst() + .orElse(null); } } diff --git a/storage-targets/cds-feature-attachments-oss/src/test/java/com/sap/cds/feature/attachments/oss/client/GoogleClientIT.java b/storage-targets/cds-feature-attachments-oss/src/test/java/com/sap/cds/feature/attachments/oss/client/GoogleClientIT.java index 759c49673..6230a58bb 100644 --- a/storage-targets/cds-feature-attachments-oss/src/test/java/com/sap/cds/feature/attachments/oss/client/GoogleClientIT.java +++ b/storage-targets/cds-feature-attachments-oss/src/test/java/com/sap/cds/feature/attachments/oss/client/GoogleClientIT.java @@ -3,44 +3,30 @@ */ package com.sap.cds.feature.attachments.oss.client; -import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assumptions.assumeTrue; import com.sap.cds.feature.attachments.oss.handler.OSSAttachmentsServiceHandlerTestUtils; +import com.sap.cloud.environment.servicebinding.api.DefaultServiceBindingAccessor; import com.sap.cloud.environment.servicebinding.api.ServiceBinding; -import java.util.HashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.junit.jupiter.api.Test; class GoogleClientIT { - // The tests in this class are intended to run against a real Google Cloud Storage instance. - // They require a valid ServiceBinding with credentials set up in the environment. @Test void testCreateReadDeleteAttachmentFlowGoogle() { - ServiceBinding binding = getRealServiceBindingGoogle(); + ServiceBinding binding = getObjectStoreBinding(); + assumeTrue(binding != null, "No Google Cloud Storage objectstore binding available"); ExecutorService executor = Executors.newCachedThreadPool(); - OSSAttachmentsServiceHandlerTestUtils.testCreateReadDeleteAttachmentFlow(binding, executor); } - private ServiceBinding getRealServiceBindingGoogle() { - // Read environment variables - String bucket = System.getenv("GS_BUCKET"); - String projectId = System.getenv("GS_PROJECT_ID"); - String base64EncodedPrivateKeyData = System.getenv("GS_BASE_64_ENCODED_PRIVATE_KEY_DATA"); - - // Return null if any are missing - if (bucket == null || projectId == null || base64EncodedPrivateKeyData == null) { - return null; - } - - ServiceBinding binding = mock(ServiceBinding.class); - HashMap creds = new HashMap<>(); - creds.put("bucket", bucket); - creds.put("projectId", projectId); - creds.put("base64EncodedPrivateKeyData", base64EncodedPrivateKeyData); - when(binding.getCredentials()).thenReturn(creds); - return binding; + private ServiceBinding getObjectStoreBinding() { + return DefaultServiceBindingAccessor.getInstance().getServiceBindings().stream() + .filter(b -> b.getServiceName().map("objectstore"::equals).orElse(false)) + .filter(b -> b.getCredentials().containsKey("base64EncodedPrivateKeyData")) + .findFirst() + .orElse(null); } } From 585c8aa8efafa8e4096ca1a15e671f2d77778921 Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Tue, 5 May 2026 12:06:57 +0200 Subject: [PATCH 11/21] improvement --- .github/actions/cf-bind/action.yml | 2 +- .github/actions/integration-tests/action.yml | 6 ++--- cds-feature-attachments/pom.xml | 27 ++++++++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/.github/actions/cf-bind/action.yml b/.github/actions/cf-bind/action.yml index 08ce16dbd..000af2067 100644 --- a/.github/actions/cf-bind/action.yml +++ b/.github/actions/cf-bind/action.yml @@ -37,7 +37,7 @@ runs: run: | for i in {1..5}; do cf login -a ${{ inputs.cf-api }} -u ${{ inputs.cf-username }} \ - -p ${{ inputs.cf-password }} -o ${{ inputs.cf-org }} -s ${{ inputs.cf-space }} && break + -p '${{ inputs.cf-password }}' -o ${{ inputs.cf-org }} -s ${{ inputs.cf-space }} && break echo "cf login failed, retrying ($i/5)..." sleep 10 if [ "$i" -eq 5 ]; then diff --git a/.github/actions/integration-tests/action.yml b/.github/actions/integration-tests/action.yml index 0b19579f0..35d2a57b0 100644 --- a/.github/actions/integration-tests/action.yml +++ b/.github/actions/integration-tests/action.yml @@ -28,12 +28,12 @@ runs: run: mvn clean install -ntp -B -pl cds-feature-attachments,storage-targets/cds-feature-attachments-fs,storage-targets/cds-feature-attachments-oss -am shell: bash - - name: Integration Tests (build version) + - name: Integration Tests run: npx cds bind --exec -- mvn clean verify -ntp -B -f ../../integration-tests/pom.xml working-directory: integration-tests/mtx-local shell: bash - - name: Integration Tests (latest CAP Java) - run: npx cds bind --exec -- mvn verify -ntp -B -f ../../integration-tests/pom.xml -P latest-test-version + - name: Client Integration Tests (OSS + Malware) + run: npx cds bind --exec -- mvn verify -ntp -B -f ../../pom.xml -pl cds-feature-attachments,storage-targets/cds-feature-attachments-oss -P integration-tests,integration-tests-oss working-directory: integration-tests/mtx-local shell: bash diff --git a/cds-feature-attachments/pom.xml b/cds-feature-attachments/pom.xml index dda78a2d7..d41393868 100644 --- a/cds-feature-attachments/pom.xml +++ b/cds-feature-attachments/pom.xml @@ -280,4 +280,31 @@ + + + integration-tests + + + + maven-failsafe-plugin + + + **/*IT.java + + + + + integration-tests + + integration-test + verify + + + + + + + + + From 1e31c29674cb219dc8726221f98d5dd7b84daf19 Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Tue, 5 May 2026 12:14:31 +0200 Subject: [PATCH 12/21] update --- .github/actions/cf-bind/action.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/actions/cf-bind/action.yml b/.github/actions/cf-bind/action.yml index 000af2067..9f9bb58ac 100644 --- a/.github/actions/cf-bind/action.yml +++ b/.github/actions/cf-bind/action.yml @@ -34,10 +34,14 @@ runs: - name: CF Login shell: bash + env: + CF_USERNAME: ${{ inputs.cf-username }} + CF_PASSWORD: ${{ inputs.cf-password }} run: | for i in {1..5}; do - cf login -a ${{ inputs.cf-api }} -u ${{ inputs.cf-username }} \ - -p '${{ inputs.cf-password }}' -o ${{ inputs.cf-org }} -s ${{ inputs.cf-space }} && break + cf api "${{ inputs.cf-api }}" && \ + cf auth && \ + cf target -o "${{ inputs.cf-org }}" -s "${{ inputs.cf-space }}" && break echo "cf login failed, retrying ($i/5)..." sleep 10 if [ "$i" -eq 5 ]; then From ac12766631ba12397a18cc303132593ceee59f8b Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Wed, 6 May 2026 08:46:46 +0200 Subject: [PATCH 13/21] cahnge npm i --- .github/actions/cf-bind/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/cf-bind/action.yml b/.github/actions/cf-bind/action.yml index 9f9bb58ac..d7581563e 100644 --- a/.github/actions/cf-bind/action.yml +++ b/.github/actions/cf-bind/action.yml @@ -52,7 +52,7 @@ runs: - name: Install CDS dependencies shell: bash - run: npm ci + run: npm i working-directory: integration-tests/mtx-local - name: Bind objectstore From 5f1c07d316aed27313317f5ffbbd3da9828f1961 Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Wed, 6 May 2026 09:45:34 +0200 Subject: [PATCH 14/21] add cds-dk --- .github/actions/cf-bind/action.yml | 10 +++++++--- .github/actions/integration-tests/action.yml | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/actions/cf-bind/action.yml b/.github/actions/cf-bind/action.yml index d7581563e..a2a993fe2 100644 --- a/.github/actions/cf-bind/action.yml +++ b/.github/actions/cf-bind/action.yml @@ -50,6 +50,10 @@ runs: fi done + - name: Install @sap/cds-dk + shell: bash + run: npm i -g @sap/cds-dk + - name: Install CDS dependencies shell: bash run: npm i @@ -60,7 +64,7 @@ runs: working-directory: integration-tests/mtx-local run: | for i in {1..5}; do - npx cds bind os -2 os:pipeline && break + cds bind os -2 os:pipeline && break echo "cds bind objectstore failed, retrying ($i/5)..." sleep 30 if [ "$i" -eq 5 ]; then @@ -73,10 +77,10 @@ runs: if: inputs.auth-method == 'basic' shell: bash working-directory: integration-tests/mtx-local - run: npx cds bind malware -2 malware:malware-key-basic + run: cds bind malware -2 malware:malware-key-basic - name: Bind malware-scanner (mtls) if: inputs.auth-method == 'mtls' shell: bash working-directory: integration-tests/mtx-local - run: npx cds bind malware -2 malware:malware-key-mtls + run: cds bind malware -2 malware:malware-key-mtls diff --git a/.github/actions/integration-tests/action.yml b/.github/actions/integration-tests/action.yml index 35d2a57b0..01b4e54c9 100644 --- a/.github/actions/integration-tests/action.yml +++ b/.github/actions/integration-tests/action.yml @@ -29,11 +29,11 @@ runs: shell: bash - name: Integration Tests - run: npx cds bind --exec -- mvn clean verify -ntp -B -f ../../integration-tests/pom.xml + run: cds bind --exec -- mvn clean verify -ntp -B -f ../../integration-tests/pom.xml working-directory: integration-tests/mtx-local shell: bash - name: Client Integration Tests (OSS + Malware) - run: npx cds bind --exec -- mvn verify -ntp -B -f ../../pom.xml -pl cds-feature-attachments,storage-targets/cds-feature-attachments-oss -P integration-tests,integration-tests-oss + run: cds bind --exec -- mvn verify -ntp -B -f ../../pom.xml -pl cds-feature-attachments,storage-targets/cds-feature-attachments-oss -P integration-tests,integration-tests-oss working-directory: integration-tests/mtx-local shell: bash From e30d1925f6ec54868f437243a4ad2c805fff518b Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Wed, 6 May 2026 09:52:15 +0200 Subject: [PATCH 15/21] add install-node.skip --- .github/actions/integration-tests/action.yml | 6 +++--- .github/actions/scan-with-sonar/action.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/actions/integration-tests/action.yml b/.github/actions/integration-tests/action.yml index 01b4e54c9..1e8243f0f 100644 --- a/.github/actions/integration-tests/action.yml +++ b/.github/actions/integration-tests/action.yml @@ -25,15 +25,15 @@ runs: maven-version: ${{ inputs.maven-version }} - name: Build dependencies for integration tests - run: mvn clean install -ntp -B -pl cds-feature-attachments,storage-targets/cds-feature-attachments-fs,storage-targets/cds-feature-attachments-oss -am + run: mvn clean install -ntp -B -pl cds-feature-attachments,storage-targets/cds-feature-attachments-fs,storage-targets/cds-feature-attachments-oss -am -Dcds.install-node.skip shell: bash - name: Integration Tests - run: cds bind --exec -- mvn clean verify -ntp -B -f ../../integration-tests/pom.xml + run: cds bind --exec -- mvn clean verify -ntp -B -f ../../integration-tests/pom.xml -Dcds.install-node.skip working-directory: integration-tests/mtx-local shell: bash - name: Client Integration Tests (OSS + Malware) - run: cds bind --exec -- mvn verify -ntp -B -f ../../pom.xml -pl cds-feature-attachments,storage-targets/cds-feature-attachments-oss -P integration-tests,integration-tests-oss + run: cds bind --exec -- mvn verify -ntp -B -f ../../pom.xml -pl cds-feature-attachments,storage-targets/cds-feature-attachments-oss -P integration-tests,integration-tests-oss -Dcds.install-node.skip working-directory: integration-tests/mtx-local shell: bash diff --git a/.github/actions/scan-with-sonar/action.yml b/.github/actions/scan-with-sonar/action.yml index 0258878d2..6bfb94548 100644 --- a/.github/actions/scan-with-sonar/action.yml +++ b/.github/actions/scan-with-sonar/action.yml @@ -39,7 +39,7 @@ runs: - name: Build project for SonarQube scan run: | - mvn clean verify -ntp -B + mvn clean verify -ntp -B -Dcds.install-node.skip shell: bash - name: Verify JaCoCo reports exist From d902d327108a61750f95a44c77d4a6f96bace900 Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Wed, 6 May 2026 10:29:17 +0200 Subject: [PATCH 16/21] add unit-tests and improve cf-bind --- .github/actions/cf-bind/action.yml | 4 ++- .github/actions/scan-with-codeql/action.yml | 6 +++- .github/workflows/pipeline.yml | 35 ++++++++++++++++++++- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/.github/actions/cf-bind/action.yml b/.github/actions/cf-bind/action.yml index a2a993fe2..1b34fa09f 100644 --- a/.github/actions/cf-bind/action.yml +++ b/.github/actions/cf-bind/action.yml @@ -52,7 +52,9 @@ runs: - name: Install @sap/cds-dk shell: bash - run: npm i -g @sap/cds-dk + run: | + npm i -g @sap/cds-dk + echo "$(npm config get prefix)/bin" >> $GITHUB_PATH - name: Install CDS dependencies shell: bash diff --git a/.github/actions/scan-with-codeql/action.yml b/.github/actions/scan-with-codeql/action.yml index 4be2598e3..6ccd08f7c 100644 --- a/.github/actions/scan-with-codeql/action.yml +++ b/.github/actions/scan-with-codeql/action.yml @@ -30,8 +30,12 @@ runs: languages: java-kotlin build-mode: manual + - name: Install @sap/cds-dk + run: npm i -g @sap/cds-dk + shell: bash + - name: Build Java code - run: mvn clean compile -B -ntp + run: mvn clean compile -B -ntp -Dcds.install-node.skip shell: bash - name: Perform CodeQL Analysis diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 10e74fcf4..cfd260270 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -38,8 +38,41 @@ jobs: - name: Spotless Check run: mvn spotless:check -Dspotless.check.skip=false -B -ntp + tests: + name: Tests (Java ${{ matrix.java-version }}) + runs-on: ubuntu-latest + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + java-version: [ 17, 21 ] + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} + + - name: Set up Java ${{ matrix.java-version }} + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: ${{ matrix.java-version }} + distribution: sapmachine + cache: maven + + - name: Set up Maven + uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5 + with: + maven-version: ${{ env.MAVEN_VERSION }} + + - name: Install @sap/cds-dk + run: npm i -g @sap/cds-dk + shell: bash + + - name: Run Tests + run: mvn test -ntp -B -P skip-integration-tests -Dcds.install-node.skip + integration-tests: - name: ITests (Java ${{ matrix.java-version }}, ${{ matrix.auth-method }}, ${{ matrix.hyperscaler }}) + name: Integration Tests (Java ${{ matrix.java-version }}, ${{ matrix.auth-method }}, ${{ matrix.hyperscaler }}) runs-on: ubuntu-latest timeout-minutes: 30 strategy: From 2581bd4dc932b9685ff4fb556e8dc890f7a99922 Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Wed, 6 May 2026 11:19:05 +0200 Subject: [PATCH 17/21] update --- .github/actions/integration-tests/action.yml | 8 ++++++-- .github/workflows/pipeline.yml | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/actions/integration-tests/action.yml b/.github/actions/integration-tests/action.yml index 1e8243f0f..2e311d8ad 100644 --- a/.github/actions/integration-tests/action.yml +++ b/.github/actions/integration-tests/action.yml @@ -28,8 +28,12 @@ runs: run: mvn clean install -ntp -B -pl cds-feature-attachments,storage-targets/cds-feature-attachments-fs,storage-targets/cds-feature-attachments-oss -am -Dcds.install-node.skip shell: bash - - name: Integration Tests - run: cds bind --exec -- mvn clean verify -ntp -B -f ../../integration-tests/pom.xml -Dcds.install-node.skip + - name: Generic Integration Tests + run: mvn clean verify -ntp -B -f integration-tests/pom.xml -pl :cds-feature-attachments-integration-tests-parent,:cds-feature-attachments-integration-tests-db,:cds-feature-attachments-integration-tests-generic -Dcds.install-node.skip + shell: bash + + - name: MTX-Local Integration Tests + run: cds bind --exec -- mvn clean verify -ntp -B -f ../../integration-tests/mtx-local/srv/pom.xml -Dcds.install-node.skip working-directory: integration-tests/mtx-local shell: bash diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index cfd260270..2b86c2174 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -112,6 +112,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} + fetch-depth: 0 - name: Bind CF Services uses: ./.github/actions/cf-bind From c57b47d4f20c2566c63615f784f9f3a454fda0ef Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Wed, 6 May 2026 20:28:00 +0200 Subject: [PATCH 18/21] restrict action usage to upstream main --- .github/workflows/main.yml | 4 ++-- .github/workflows/pipeline.yml | 10 +++++----- .github/workflows/pr.yml | 2 +- .github/workflows/release.yml | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1e19a3d1d..cb0494971 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Scan With Black Duck - uses: ./.github/actions/scan-with-blackduck + uses: cap-java/cds-feature-attachments/.github/actions/scan-with-blackduck@main with: blackduck_token: ${{ secrets.BLACK_DUCK_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }} @@ -32,5 +32,5 @@ jobs: scan_mode: RAPID build-and-test: - uses: ./.github/workflows/pipeline.yml + uses: cap-java/cds-feature-attachments/.github/workflows/pipeline.yml@main secrets: inherit diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 2b86c2174..56d17806c 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -88,7 +88,7 @@ jobs: ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} - name: Bind CF Services - uses: ./.github/actions/cf-bind + uses: cap-java/cds-feature-attachments/.github/actions/cf-bind@main with: cf-api: ${{ secrets[format('CF_API_{0}', matrix.hyperscaler)] }} cf-username: ${{ secrets.CF_USERNAME }} @@ -98,7 +98,7 @@ jobs: auth-method: ${{ matrix.auth-method }} - name: Integration Tests - uses: ./.github/actions/integration-tests + uses: cap-java/cds-feature-attachments/.github/actions/integration-tests@main with: java-version: ${{ matrix.java-version }} maven-version: ${{ env.MAVEN_VERSION }} @@ -115,7 +115,7 @@ jobs: fetch-depth: 0 - name: Bind CF Services - uses: ./.github/actions/cf-bind + uses: cap-java/cds-feature-attachments/.github/actions/cf-bind@main with: cf-api: ${{ secrets.CF_API_AWS }} cf-username: ${{ secrets.CF_USERNAME }} @@ -125,7 +125,7 @@ jobs: auth-method: basic - name: SonarQube Scan - uses: ./.github/actions/scan-with-sonar + uses: cap-java/cds-feature-attachments/.github/actions/scan-with-sonar@main with: java-version: 17 maven-version: ${{ env.MAVEN_VERSION }} @@ -148,7 +148,7 @@ jobs: ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} - name: CodeQL Analysis - uses: ./.github/actions/scan-with-codeql + uses: cap-java/cds-feature-attachments/.github/actions/scan-with-codeql@main with: java-version: 17 maven-version: ${{ env.MAVEN_VERSION }} diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 1cb329519..ca8b259c2 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -25,5 +25,5 @@ jobs: build-and-test: needs: requires-approval if: always() && (needs.requires-approval.result == 'success' || needs.requires-approval.result == 'skipped') - uses: ./.github/workflows/pipeline.yml + uses: cap-java/cds-feature-attachments/.github/workflows/pipeline.yml@main secrets: inherit diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8bccdaa10..805da331d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Scan With Black Duck - uses: ./.github/actions/scan-with-blackduck + uses: cap-java/cds-feature-attachments/.github/actions/scan-with-blackduck@main with: blackduck_token: ${{ secrets.BLACK_DUCK_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }} @@ -39,7 +39,7 @@ jobs: token: ${{ secrets.GH_TOKEN }} - name: Update version - uses: ./.github/actions/newrelease + uses: cap-java/cds-feature-attachments/.github/actions/newrelease@main with: java-version: ${{ env.JAVA_VERSION }} maven-version: ${{ env.MAVEN_VERSION }} @@ -74,13 +74,13 @@ jobs: name: root-new-version - name: Build - uses: ./.github/actions/build + uses: cap-java/cds-feature-attachments/.github/actions/build@main with: java-version: ${{ env.JAVA_VERSION }} maven-version: ${{ env.MAVEN_VERSION }} - name: Sonar Scan - uses: ./.github/actions/scan-with-sonar + uses: cap-java/cds-feature-attachments/.github/actions/scan-with-sonar@main with: java-version: ${{ env.JAVA_VERSION }} maven-version: ${{ env.MAVEN_VERSION }} @@ -106,7 +106,7 @@ jobs: name: root-build - name: Deploy - uses: ./.github/actions/deploy-release + uses: cap-java/cds-feature-attachments/.github/actions/deploy-release@main with: user: ${{ secrets.CENTRAL_REPOSITORY_USER }} password: ${{ secrets.CENTRAL_REPOSITORY_PASS }} From 5aee24d81d4598416f8e34e3b2fe3d2f2eab4ca3 Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Thu, 7 May 2026 09:35:51 +0200 Subject: [PATCH 19/21] replace blackduck curl with blackduck action --- .../actions/scan-with-blackduck/action.yml | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/.github/actions/scan-with-blackduck/action.yml b/.github/actions/scan-with-blackduck/action.yml index 2e69261ce..b9d1e21d5 100644 --- a/.github/actions/scan-with-blackduck/action.yml +++ b/.github/actions/scan-with-blackduck/action.yml @@ -41,23 +41,20 @@ runs: echo "REVISION=$(mvn help:evaluate -Dexpression=revision -q -DforceStdout)" >> $GITHUB_OUTPUT shell: bash - - name: BlackDuck Detect Scan - run: | - bash <(curl -s -L https://detect.synopsys.com/detect9.sh) \ - --blackduck.url=https://sap.blackducksoftware.com/ \ - --blackduck.api.token="${BLACKDUCK_TOKEN}" \ - --detect.project.name=com.sap.cds.feature.attachments \ - --detect.project.version.name="${REVISION}" \ - --detect.included.detector.types=MAVEN \ - --detect.excluded.directories='**/node_modules,**/*test*,**/localrepo,**/target/site,**/*-site.jar,**/samples/**' \ - --detect.maven.excluded.modules=integration-tests,integration-tests/db,integration-tests/generic,integration-tests/mtx-local/srv \ - --detect.maven.build.command='-pl com.sap.cds:cds-feature-attachments' \ - --detect.tools=DETECTOR,BINARY_SCAN \ - --detect.blackduck.scan.mode="${SCAN_MODE}" \ - --detect.risk.report.pdf=false \ + - name: BlackDuck Security Scan + uses: blackduck-inc/black-duck-security-scan@v2 + with: + blackducksca_url: https://sap.blackducksoftware.com/ + blackducksca_token: ${{ inputs.blackduck_token }} + blackducksca_scan_full: ${{ inputs.scan_mode == 'FULL' }} + github_token: ${{ inputs.github_token }} + detect_args: > + --detect.project.name=com.sap.cds.feature.attachments + --detect.project.version.name=${{ steps.get-revision.outputs.REVISION }} + --detect.included.detector.types=MAVEN + --detect.excluded.directories=**/node_modules,**/*test*,**/localrepo,**/target/site,**/*-site.jar,**/samples/** + --detect.maven.excluded.modules=integration-tests,integration-tests/db,integration-tests/generic,integration-tests/mtx-local/srv + --detect.maven.build.command=-pl com.sap.cds:cds-feature-attachments + --detect.tools=DETECTOR,BINARY_SCAN + --detect.risk.report.pdf=false --logging.level.detect=INFO - shell: bash - env: - BLACKDUCK_TOKEN: ${{ inputs.blackduck_token }} - SCAN_MODE: ${{ inputs.scan_mode }} - REVISION: ${{ steps.get-revision.outputs.REVISION }} From e8f5b421b3c9d13af852666271d7c31591c40927 Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Thu, 7 May 2026 09:47:15 +0200 Subject: [PATCH 20/21] minor improvements --- .github/actions/cf-bind/action.yml | 13 ++++++++----- .github/actions/scan-with-sonar/action.yml | 3 ++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/actions/cf-bind/action.yml b/.github/actions/cf-bind/action.yml index 1b34fa09f..7baa0410e 100644 --- a/.github/actions/cf-bind/action.yml +++ b/.github/actions/cf-bind/action.yml @@ -37,24 +37,27 @@ runs: env: CF_USERNAME: ${{ inputs.cf-username }} CF_PASSWORD: ${{ inputs.cf-password }} + CF_API: ${{ inputs.cf-api }} + CF_ORG: ${{ inputs.cf-org }} + CF_SPACE: ${{ inputs.cf-space }} run: | for i in {1..5}; do - cf api "${{ inputs.cf-api }}" && \ + cf api "$CF_API" && \ cf auth && \ - cf target -o "${{ inputs.cf-org }}" -s "${{ inputs.cf-space }}" && break - echo "cf login failed, retrying ($i/5)..." - sleep 10 + cf target -o "$CF_ORG" -s "$CF_SPACE" && break if [ "$i" -eq 5 ]; then echo "cf login failed after 5 attempts." exit 1 fi + echo "cf login failed, retrying ($i/5)..." + sleep 10 done - name: Install @sap/cds-dk shell: bash run: | npm i -g @sap/cds-dk - echo "$(npm config get prefix)/bin" >> $GITHUB_PATH + echo "$(npm config get prefix)/bin" >> "${GITHUB_PATH}" - name: Install CDS dependencies shell: bash diff --git a/.github/actions/scan-with-sonar/action.yml b/.github/actions/scan-with-sonar/action.yml index 6bfb94548..abf626eef 100644 --- a/.github/actions/scan-with-sonar/action.yml +++ b/.github/actions/scan-with-sonar/action.yml @@ -65,7 +65,7 @@ runs: run: > mvn org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.host.url=https://sonar.tools.sap - -Dsonar.token=${{ inputs.sonarq-token }} + -Dsonar.token="${SONAR_TOKEN}" -Dsonar.projectKey=cds-feature-attachments -Dsonar.projectVersion=${{ steps.get-revision.outputs.REVISION }} -Dsonar.qualitygate.wait=true @@ -77,3 +77,4 @@ runs: shell: bash env: GITHUB_TOKEN: ${{ inputs.github-token }} + SONAR_TOKEN: ${{ inputs.sonarq-token }} From 9b76075570b78b095b5065de4e07b7ca71405313 Mon Sep 17 00:00:00 2001 From: Marvin Lindner Date: Thu, 7 May 2026 09:59:26 +0200 Subject: [PATCH 21/21] add approval step to release --- .github/workflows/release.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 805da331d..6e3c93e46 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,7 +11,16 @@ on: types: [ "released" ] jobs: + requires-approval: + runs-on: ubuntu-latest + name: "Waiting for release approval" + environment: release-approval + steps: + - name: Approval Step + run: echo "Release has been approved!" + blackduck: + needs: requires-approval name: Blackduck Scan runs-on: ubuntu-latest timeout-minutes: 30 @@ -27,6 +36,7 @@ jobs: maven-version: ${{ env.MAVEN_VERSION }} update-version: + needs: requires-approval name: Update Version runs-on: ubuntu-latest timeout-minutes: 30