-
Notifications
You must be signed in to change notification settings - Fork 0
Review: Full prototype implementation #49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Schmarvinius
wants to merge
42
commits into
review-base
Choose a base branch
from
main
base: review-base
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
42 commits
Select commit
Hold shift + click to select a range
0b5430a
Add workflows for main, prs to main and scan with blackduck and sonar…
lisajulia 4f2a43b
Add README.md
lisajulia d0ad47d
Initial version
lisajulia 3067a41
Add artifacts for deployment
lisajulia 6bb6126
Actually provide option to define custom resource group for single
lisajulia ef6e8a5
Fix name in package.json
lisajulia f9c0d70
Cleanup: pom, unneeded files
lisajulia a65799f
Update srv/src/main/java/com/sap/cds/feature/ai/client/setup/AICoreSe…
lisajulia 99076c1
Update README.md
lisajulia 8c77bd0
Update REUSE.toml
lisajulia 88aca3d
Rename AICoreSetup -> AICoreSetupHandler + some cosmetics
lisajulia 28143ce
Remove .DS_Store
lisajulia a36deff
Adjust Readme: aicore handling availabe with first version
lisajulia ca15eab
Use the binding and not the environment variable for the integration …
lisajulia 29dedcc
Add blackduck and codeql action
lisajulia edb792a
Version bumps
lisajulia 0ff1ff0
Migrate codebase from internal fork (multi-module structure) (#18)
Schmarvinius b48f76a
chore(hyperspace): 🤖 Add PR Bot Configuration (#15)
hyperspace-insights[bot] 15c1569
chore: bootstrap ci/cd workflows (#19)
Schmarvinius be2c2b3
fix: run npm ci before cds build in integration-tests (#17) (#21)
Schmarvinius 11e8f96
fix: filter recommendations to unfilled fields only (#22) (#23)
Schmarvinius 8df01f4
fix(itest): repair resource-group cleanup so quota does not leak (#24…
Schmarvinius 5f8a3fd
Bump the minor-patch group across 1 directory with 5 updates (#20)
dependabot[bot] 99999e0
fix(mtx): wire MTX subscribe lifecycle for mock AI Core service (#26)…
Schmarvinius 5ed1f09
fix: use idiomatic patterns for error messages and stream collection …
Schmarvinius 45a18eb
refactor: introduce AICoreElements constants; refactor DeploymentHand…
Schmarvinius 3fe47d2
refactor: slim AICoreService interface to public API surface (#42)
Schmarvinius 7368c7f
fix: cleanup sonar-* resource groups in CI (#38) (#46)
Schmarvinius 27b95c3
refactor: decompose FioriRecommendationHandler into focused helpers (…
Schmarvinius c189148
refactor: accept SDK API clients as constructor parameters (#44)
Schmarvinius 24abc83
docs: document RptInferenceClient as intentional public API (#45)
Schmarvinius 911da7d
fix: resolve empty JaCoCo aggregate report for SonarQube coverage
Schmarvinius 0f008dd
add reuse (#51)
Schmarvinius 32c9ee9
fix: add assertion to delete_resourceGroup test case (#50)
Schmarvinius 24106ff
chore: update repo references from cds-feature-ai to cds-ai (#52)
Schmarvinius 5a3ba6d
Update Reuse Badge (#53)
Schmarvinius 40e1f3d
chore(deps): bump the minor-patch group across 1 directory with 2 upd…
dependabot[bot] 060c4ff
chore(deps): bump actions/stale in the minor-patch group (#47)
dependabot[bot] edb800f
chore: use shared org-level GitHub Actions and workflows (#55)
Schmarvinius e24fdb9
chore: code review cleanup before review (#57)
Schmarvinius 6bbb6fc
refactor: Migrate API Packages (#69)
Schmarvinius 24aa02c
Comments from #49: Tenant Scoping (#68)
lisajulia File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| { | ||
| "maxDocCommentLine": 80, | ||
| "formatDocComments": true, | ||
| "tabSize": 2, | ||
| "alignPostAnnotations": false, | ||
| "alignColonsInAnnotations": false, | ||
| "alignValuesInAnnotations": false | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # Each pull request will require review and approval from the code owners | ||
| # before it can be merged. | ||
| # | ||
| # Learn more: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners | ||
|
|
||
| # Global ownership — cdsmunich team owns everything | ||
| * @cap-java/cdsmunich |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| name: Bind Cloud Foundry Services | ||
| description: Login to CF and bind the AI Core service 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 | ||
|
|
||
| runs: | ||
| using: composite | ||
| steps: | ||
| - name: CF Login | ||
| uses: cap-java/.github/actions/cf-login@296573b55e906f5c77a1855bcfe4285cbbc5cac4 # main | ||
| with: | ||
| cf-api: ${{ inputs.cf-api }} | ||
| cf-username: ${{ inputs.cf-username }} | ||
| cf-password: ${{ inputs.cf-password }} | ||
| cf-org: ${{ inputs.cf-org }} | ||
| cf-space: ${{ inputs.cf-space }} | ||
|
|
||
| - name: Install @sap/cds-dk | ||
| shell: bash | ||
| run: | | ||
| npm i -g @sap/cds-dk@9.9.1 | ||
| echo "$(npm config get prefix)/bin" >> "${GITHUB_PATH}" | ||
|
|
||
| - name: Install CDS dependencies | ||
| shell: bash | ||
| run: npm ci || npm install | ||
| working-directory: integration-tests | ||
|
|
||
| - name: Bind ai-core | ||
| shell: bash | ||
| working-directory: integration-tests | ||
| run: | | ||
| for i in {1..5}; do | ||
| cds bind ai-core -2 ai-core:ai-core-key && break | ||
| if [ "$i" -eq 5 ]; then | ||
| echo "cds bind ai-core failed after 5 attempts." | ||
| exit 1 | ||
| fi | ||
| echo "cds bind ai-core failed, retrying ($i/5)..." | ||
| sleep 30 | ||
| done |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| name: Integration Tests | ||
| description: Run integration tests using Maven with cds bind for service bindings. | ||
|
|
||
| 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@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 | ||
| with: | ||
| java-version: ${{ inputs.java-version }} | ||
| distribution: sapmachine | ||
| cache: maven | ||
|
|
||
| - name: Setup Maven ${{ inputs.maven-version }} | ||
| uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5 | ||
| with: | ||
| maven-version: ${{ inputs.maven-version }} | ||
|
|
||
| - name: Build dependencies for integration tests | ||
| run: mvn clean install -ntp -B -pl cds-feature-ai-core,cds-feature-recommendations,cds-starter-ai -am -DskipTests | ||
| shell: bash | ||
|
|
||
| - name: Integration Tests (spring) | ||
| env: | ||
| CDS_AICORE_TEST_RESOURCE_GROUP: itest-${{ github.run_id }}-${{ github.run_attempt }}-j${{ inputs.java-version }} | ||
| run: cds bind --exec -- mvn clean verify -ntp -B -f pom.xml | ||
| working-directory: integration-tests | ||
| shell: bash | ||
|
|
||
| - name: Cleanup AI Core test resource groups | ||
| if: always() | ||
| working-directory: integration-tests | ||
| shell: bash | ||
| env: | ||
| RESOURCE_GROUP_PREFIX: itest-${{ github.run_id }}-${{ github.run_attempt }}-j${{ inputs.java-version }} | ||
| run: cds bind --exec -- node ${{ github.workspace }}/.github/scripts/cleanup-resource-groups.js |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| name: Scan with SonarQube | ||
| description: Scans the project with SonarQube. Caller is responsible for setting up the CF binding (e.g. via the cf-bind action) before invoking this action. | ||
|
|
||
| inputs: | ||
| sonarq-token: | ||
| description: The token to use for SonarQube authentication | ||
| required: true | ||
| github-token: | ||
| description: The token to use for GitHub authentication | ||
| required: true | ||
| java-version: | ||
| description: The version of Java to use | ||
| required: true | ||
| maven-version: | ||
| description: The version of Maven to use | ||
| 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: Get Revision | ||
| id: get-revision | ||
| run: | | ||
| echo "REVISION=$(mvn help:evaluate -Dexpression=revision -q -DforceStdout)" >> "$GITHUB_OUTPUT" | ||
| shell: bash | ||
|
|
||
| - name: Build and test main modules | ||
| run: mvn clean install -ntp -B -pl cds-feature-ai-core,cds-feature-recommendations,cds-starter-ai -am | ||
| shell: bash | ||
|
|
||
| - name: Run integration tests | ||
| env: | ||
| CDS_AICORE_TEST_RESOURCE_GROUP: sonar-${{ github.run_id }}-${{ github.run_attempt }} | ||
| run: cds bind --exec -- mvn clean verify install -ntp -B | ||
| working-directory: integration-tests | ||
| shell: bash | ||
|
|
||
| - name: Cleanup AI Core test resource groups | ||
| if: always() | ||
| working-directory: integration-tests | ||
| shell: bash | ||
| env: | ||
| RESOURCE_GROUP_PREFIX: sonar-${{ github.run_id }}-${{ github.run_attempt }} | ||
| run: cds bind --exec -- node ${{ github.workspace }}/.github/scripts/cleanup-resource-groups.js | ||
|
|
||
| - name: Generate aggregate coverage report | ||
| run: mvn verify -ntp -B -pl coverage-report -am -DskipTests | ||
| shell: bash | ||
|
|
||
| - name: Verify JaCoCo reports exist | ||
| run: | | ||
| echo "=== Checking JaCoCo reports ===" | ||
| find . -name "jacoco.xml" -type f | ||
| if [ -f "coverage-report/target/site/jacoco-aggregate/jacoco.xml" ]; then | ||
| echo "Found: coverage-report/target/site/jacoco-aggregate/jacoco.xml" | ||
| else | ||
| echo "Missing: coverage-report/target/site/jacoco-aggregate/jacoco.xml" | ||
| exit 1 | ||
| fi | ||
| shell: bash | ||
|
|
||
| - name: SonarQube Scan | ||
| run: > | ||
| mvn org.sonarsource.scanner.maven:sonar-maven-plugin:sonar | ||
| -Dsonar.host.url=https://sonar.tools.sap | ||
| -Dsonar.token="${SONAR_TOKEN}" | ||
| -Dsonar.projectKey=com.sap.cds.cds-ai | ||
| -Dsonar.projectVersion=${{ steps.get-revision.outputs.REVISION }} | ||
| -Dsonar.qualitygate.wait=true | ||
| -Dsonar.java.source=17 | ||
| -Dsonar.exclusions=**/samples/**,**/integration-tests/** | ||
| -Dsonar.coverage.jacoco.xmlReportPaths=${{ github.workspace }}/cds-feature-ai-core/target/site/jacoco/jacoco.xml,${{ github.workspace }}/cds-feature-recommendations/target/site/jacoco/jacoco.xml,${{ github.workspace }}/integration-tests/spring/target/site/jacoco/jacoco.xml,${{ github.workspace }}/coverage-report/target/site/jacoco-aggregate/jacoco.xml | ||
| -Dsonar.coverage.exclusions=**/src/test/**,**/src/gen/** | ||
| -B -ntp | ||
| shell: bash | ||
| env: | ||
| GITHUB_TOKEN: ${{ inputs.github-token }} | ||
| SONAR_TOKEN: ${{ inputs.sonarq-token }} | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| version: 2 | ||
| updates: | ||
| - package-ecosystem: maven | ||
| directories: | ||
| - "/" | ||
| schedule: | ||
| interval: weekly | ||
| cooldown: | ||
| default-days: 7 | ||
| groups: | ||
| minor-patch: | ||
| patterns: | ||
| - "*" | ||
| update-types: | ||
| - minor | ||
| - patch | ||
|
|
||
| - package-ecosystem: github-actions | ||
| directory: "/" | ||
| schedule: | ||
| interval: weekly | ||
| cooldown: | ||
| default-days: 7 | ||
| groups: | ||
| minor-patch: | ||
| patterns: | ||
| - "*" | ||
| update-types: | ||
| - minor | ||
| - patch |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| /** | ||
| * Cleans up AI Core test resource groups. | ||
| * | ||
| * Required environment variables: | ||
| * RESOURCE_GROUP_PREFIX - The prefix identifying resource groups owned by this run | ||
| * (e.g. "itest-12345-1-j17" or "sonar-12345-1") | ||
| * | ||
| * Optional environment variables: | ||
| * STALE_PREFIXES - Comma-separated list of additional prefixes to clean up | ||
| * (defaults to "itest-rg-,cds-itest-") | ||
| * | ||
| * Credentials are resolved from VCAP_SERVICES (via cds bind) or AICORE_SERVICE_KEY. | ||
| */ | ||
| const https = require("https"); | ||
|
|
||
| const DEFAULT_STALE_PREFIXES = ["itest-rg-", "cds-itest-"]; | ||
|
|
||
| function getCredentials() { | ||
| const vcap = JSON.parse(process.env.VCAP_SERVICES || "{}"); | ||
| return ( | ||
| (vcap.aicore || vcap["ai-core"] || [{}])[0].credentials || | ||
| JSON.parse(process.env.AICORE_SERVICE_KEY || "null") | ||
| ); | ||
| } | ||
|
|
||
| function request(url, opts = {}) { | ||
| return new Promise((resolve, reject) => { | ||
| const u = new URL(url); | ||
| const req = https.request( | ||
| { | ||
| hostname: u.hostname, | ||
| path: u.pathname + u.search, | ||
| method: opts.method || "GET", | ||
| headers: opts.headers || {}, | ||
| }, | ||
| (res) => { | ||
| let data = ""; | ||
| res.on("data", (chunk) => (data += chunk)); | ||
| res.on("end", () => resolve({ status: res.statusCode, body: data })); | ||
| } | ||
| ); | ||
| req.on("error", reject); | ||
| if (opts.body) req.write(opts.body); | ||
| req.end(); | ||
| }); | ||
| } | ||
|
|
||
| async function getAccessToken(credentials) { | ||
| const tokenUrl = credentials.url + "/oauth/token"; | ||
| const params = new URLSearchParams({ grant_type: "client_credentials" }); | ||
| const authHeader = | ||
| "Basic " + | ||
| Buffer.from(credentials.clientid + ":" + credentials.clientsecret).toString( | ||
| "base64" | ||
| ); | ||
| const res = await request(tokenUrl + "?" + params.toString(), { | ||
| headers: { Authorization: authHeader }, | ||
| }); | ||
| return JSON.parse(res.body).access_token; | ||
| } | ||
|
|
||
| async function deleteResourceGroups(apiUrl, headers, prefixes) { | ||
| const res = await request(apiUrl + "/v2/admin/resourceGroups", { headers }); | ||
| const groups = JSON.parse(res.body).resources || []; | ||
| const toDelete = groups.filter( | ||
| (rg) => | ||
| rg.resourceGroupId && | ||
| prefixes.some((p) => rg.resourceGroupId.startsWith(p)) | ||
| ); | ||
|
|
||
| for (const rg of toDelete) { | ||
| const delRes = await request( | ||
| apiUrl + "/v2/admin/resourceGroups/" + rg.resourceGroupId, | ||
| { method: "DELETE", headers } | ||
| ); | ||
| console.log("Delete", rg.resourceGroupId, "->", delRes.status); | ||
| } | ||
|
|
||
| console.log("Cleaned up", toDelete.length, "resource groups"); | ||
| } | ||
|
|
||
| async function main() { | ||
| const ownPrefix = process.env.RESOURCE_GROUP_PREFIX; | ||
| if (!ownPrefix) { | ||
| console.error("RESOURCE_GROUP_PREFIX environment variable is required"); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| const credentials = getCredentials(); | ||
| if (!credentials) { | ||
| console.log("No AI Core credentials found, skipping cleanup"); | ||
| return; | ||
| } | ||
|
|
||
| const stalePrefixes = process.env.STALE_PREFIXES | ||
| ? process.env.STALE_PREFIXES.split(",").map((s) => s.trim()) | ||
| : DEFAULT_STALE_PREFIXES; | ||
|
|
||
| const prefixes = [ownPrefix, ...stalePrefixes]; | ||
|
|
||
| const apiUrl = credentials.serviceurls.AI_API_URL; | ||
| const token = await getAccessToken(credentials); | ||
| const headers = { | ||
| Authorization: "Bearer " + token, | ||
| "AI-Resource-Group": "default", | ||
| }; | ||
|
|
||
| console.log("Cleaning resource groups matching prefixes:", prefixes); | ||
| await deleteResourceGroups(apiUrl, headers, prefixes); | ||
| } | ||
|
|
||
| main().catch((e) => { | ||
| console.error(e.message); | ||
| process.exit(0); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| name: Label issues | ||
|
|
||
| permissions: {} | ||
|
|
||
| on: | ||
| issues: | ||
| types: | ||
| - opened | ||
|
|
||
| jobs: | ||
| label_issues: | ||
| uses: cap-java/.github/.github/workflows/issue.yml@296573b55e906f5c77a1855bcfe4285cbbc5cac4 # main | ||
| permissions: | ||
| issues: write |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.