From 1891a907b4a063ce1d891ace886bd4dd29b8dd46 Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Tue, 11 Nov 2025 09:47:24 +0100 Subject: [PATCH 1/2] Initial commit --- .github/workflows/deploy.yml | 122 +++++++++++++++++++++++++++++++++++ tests/non-draft-request.http | 20 +++--- 2 files changed, 132 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 00000000..bf9f8704 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,122 @@ +name: Deploy Incidents App + +on: + push: + branches: [main] + workflow_dispatch: + pull_request_target: + branches: [ main ] + types: [ reopened, synchronize, opened ] + +jobs: + requires-approval: + runs-on: ubuntu-latest + name: "Waiting for PR approval as this workflow runs on pull_request_target" + if: github.event_name == 'pull_request_target' && github.event.pull_request.base.user.login != 'cap-js' + environment: pr-approval + steps: + - name: Approval Step + run: echo "This job has been approved!" + deploy: + name: Deploy ${{ matrix.tenant }} App + runs-on: ubuntu-latest + needs: requires-approval + if: always() && (needs.requires-approval.result == 'success' || needs.requires-approval.result == 'skipped') + strategy: + matrix: + tenant: [singletenant, multitenant] + permissions: + contents: read + issues: write + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Clone Incidents App Repository + run: | + if [[ "${{ matrix.tenant }}" == "singletenant" ]]; then + git clone --branch attachmentsE2E --single-branch https://github.com/cap-js/incidents-app.git + else + git clone --branch attachmentsE2EMTX --single-branch https://github.com/cap-js/incidents-app.git + fi + + - name: Install dependencies + working-directory: incidents-app + run: npm install + - name: Use PR branch version of @cap-js/attachments + if: github.event_name == 'pull_request' + working-directory: incidents-app + run: | + BRANCH_NAME=${{ github.head_ref }} + echo "🔄 Using @cap-js/attachments branch: $BRANCH_NAME" + + # Override in app-level package.json + jq --arg url "git+https://github.com/cap-js/attachments.git#$BRANCH_NAME" \ + '.dependencies["@cap-js/attachments"] = $url' package.json > tmp.json && mv tmp.json package.json + + # Also override in mtx/sidecar if multitenant + if [[ "${{ matrix.tenant }}" == "multitenant" ]]; then + jq --arg url "git+https://github.com/cap-js/attachments.git#$BRANCH_NAME" \ + '.dependencies["@cap-js/attachments"] = $url' mtx/sidecar/package.json > tmp.json && mv tmp.json mtx/sidecar/package.json + fi + + # Install updated dependencies + npm install + if [[ "${{ matrix.tenant }}" == "multitenant" ]]; then + npm install --prefix mtx/sidecar + fi + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "22" + + - name: Install CDS CLI + run: npm install -g @sap/cds + + - name: Configure application features + working-directory: incidents-app + run: | + if [[ "${{ matrix.tenant }}" == "singletenant" ]]; then + npx cds add hana,xsuaa,workzone --for production + else + npx cds add hana,xsuaa,multitenancy --for production + fi + + - name: Fix xs-app.json destination (singletenant only) + if: matrix.tenant == 'singletenant' + working-directory: incidents-app/app/incidents + run: | + jq '(.routes[] | select(.destination == "srv-api")).destination = "incidents-testing-srv-api"' xs-app.json > tmp.json && mv tmp.json xs-app.json + + - name: Install additional dependencies + working-directory: incidents-app + run: | + npm install + npm install --prefix app/incidents + if [[ "${{ matrix.tenant }}" == "multitenant" ]]; then + npm install --prefix mtx/sidecar + npm install @sap/xsenv --prefix mtx/sidecar + fi + + - name: Freeze npm dependencies (multitenant only) + if: matrix.tenant == 'multitenant' + working-directory: incidents-app + run: | + npm update --package-lock-only + npm update --package-lock-only --prefix mtx/sidecar + + - name: Build application + working-directory: incidents-app + run: npx cds build --production + + - name: Deploy to SAP BTP Cloud Foundry + uses: ./.github/actions/deploy + 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 }} + CF_APP_NAME: ${{ matrix.tenant == 'singletenant' && 'incidents-testing' || 'incidents-testing-mtx' }} \ No newline at end of file diff --git a/tests/non-draft-request.http b/tests/non-draft-request.http index 3465ef28..92317c99 100644 --- a/tests/non-draft-request.http +++ b/tests/non-draft-request.http @@ -5,13 +5,13 @@ ### Get list of all incidents # @name incidents -GET {{host}}/odata/v4/processor/Incidents +GET {{host}}/odata/v4/admin/Incidents Authorization: {{auth}} ### Creating attachment (metadata request) @incidentsID = {{incidents.response.body.value[2].ID}} # @name createAttachment -POST {{host}}/odata/v4/processor/Incidents({{incidentsID}})/attachments +POST {{host}}/odata/v4/admin/Incidents({{incidentsID}})/attachments Authorization: {{auth}} Content-Type: application/json @@ -21,40 +21,40 @@ Content-Type: application/json ### Put attachment content (content request) @attachmentsID = {{createAttachment.response.body.ID}} -PUT {{host}}/odata/v4/processor/Incidents({{incidentsID}})/attachments(ID={{attachmentsID}})/content +PUT {{host}}/odata/v4/admin/Incidents({{incidentsID}})/attachments(ID={{attachmentsID}})/content Authorization: {{auth}} Content-Type: image/jpeg < ./integration/content/sample-1.jpg ### Get newly created attachment metadata -GET {{host}}/odata/v4/processor/Incidents({{incidentsID}})/attachments(ID={{attachmentsID}}) +GET {{host}}/odata/v4/admin/Incidents({{incidentsID}})/attachments(ID={{attachmentsID}}) Authorization: {{auth}} ### Fetching newly created attachment content -GET {{host}}/odata/v4/processor/Incidents({{incidentsID}})/attachments(ID={{attachmentsID}})/content +GET {{host}}/odata/v4/admin/Incidents({{incidentsID}})/attachments(ID={{attachmentsID}})/content Authorization: {{auth}} ### Get list of attachments for a particular incident # @name attachments -GET {{host}}/odata/v4/processor/Incidents(ID={{incidentsID}})/attachments +GET {{host}}/odata/v4/admin/Incidents(ID={{incidentsID}})/attachments Authorization: {{auth}} ### Get attachments content -GET {{host}}/odata/v4/processor/Incidents({{incidentsID}})/attachments(ID={{attachmentsID}})/content +GET {{host}}/odata/v4/admin/Incidents({{incidentsID}})/attachments(ID={{attachmentsID}})/content Authorization: {{auth}} ### Get attachments content with up__ID included -GET {{host}}/odata/v4/processor/Incidents({{incidentsID}})/attachments(up__ID={{incidentsID}},ID={{attachmentsID}})/content +GET {{host}}/odata/v4/admin/Incidents({{incidentsID}})/attachments(up__ID={{incidentsID}},ID={{attachmentsID}})/content Authorization: {{auth}} ### Put attachment content (content request) with up__ID included -PUT {{host}}/odata/v4/processor/Incidents({{incidentsID}})/attachments(up__ID={{incidentsID}},ID={{attachmentsID}})/content +PUT {{host}}/odata/v4/admin/Incidents({{incidentsID}})/attachments(up__ID={{incidentsID}},ID={{attachmentsID}})/content Authorization: {{auth}} Content-Type: image/jpeg < ./integration/content/sample-1.jpg ### Delete attachment -DELETE {{host}}/odata/v4/processor/Incidents({{incidentsID}})/attachments(ID={{attachmentsID}}) +DELETE {{host}}/odata/v4/admin/Incidents({{incidentsID}})/attachments(ID={{attachmentsID}}) Authorization: {{auth}} \ No newline at end of file From cad29ec43393c16338142e257095a06bb0155c7e Mon Sep 17 00:00:00 2001 From: Eric Peairs Date: Tue, 11 Nov 2025 10:18:50 +0100 Subject: [PATCH 2/2] Temporarily restoring old deploy file --- .github/actions/deploy/action.yml | 82 +++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 .github/actions/deploy/action.yml diff --git a/.github/actions/deploy/action.yml b/.github/actions/deploy/action.yml new file mode 100644 index 00000000..345c8479 --- /dev/null +++ b/.github/actions/deploy/action.yml @@ -0,0 +1,82 @@ +name: "Deploy to Cloud Foundry" +description: "Logs into Cloud Foundry and deploys the application" +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 + CF_APP_NAME: + description: "Cloud Foundry application name" + required: true +runs: + using: "composite" + steps: + - name: Install dependencies and Cloud Foundry CLI (v8.9.0) + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y libc6 wget tar + wget "https://packages.cloudfoundry.org/stable?release=linux64-binary&version=8.9.0&source=github-rel" -O cf-cli.tar.gz + tar -xvzf cf-cli.tar.gz + sudo mv cf /usr/local/bin/ + sudo mv cf8 /usr/local/bin/ + cf --version + + - name: Authenticate with Cloud Foundry + shell: bash + run: | + echo "::debug::CF_API=${{ inputs.CF_API }}" + for i in {1..3}; 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/3)..." + sleep 10 + if [ "$i" -eq 3 ]; then + echo "❌ cf login failed after 3 attempts." + exit 1 + fi + done + + - name: Install Multi-Target Application Build Tool (MBT) + shell: bash + run: npm install -g mbt + + - name: Check if mta.yaml Exists + shell: bash + working-directory: incidents-app + run: | + test -f mta.yaml && echo "✅ mta.yaml found!" || echo "⚠️ WARNING: mta.yaml NOT found!" + + - name: Build MTA archive + shell: bash + working-directory: incidents-app + run: mbt build -t gen --mtar mta.tar + + - name: Install Cloud Foundry MultiApps Plugin + shell: bash + run: | + cf install-plugin -f https://github.com/cloudfoundry-incubator/multiapps-cli-plugin/releases/latest/download/multiapps-plugin.linux64 + cf plugins + + - name: Undeploy existing apps if exists + shell: bash + run: | + for APP in incidents-testing incidents-testingMTX; do + echo "🔍 Attempting to undeploy $APP" + echo "y" | cf undeploy "$APP" --delete-services --delete-service-keys || echo "⚠️ $APP not found or undeploy failed" + done + + - name: Deploy to Cloud Foundry + shell: bash + working-directory: incidents-app + run: cf deploy gen/mta.tar -f