Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/auth.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Check Actor Permission

on:
workflow_dispatch:
workflow_call:

jobs:
check-permission:
name: 'Check if actor has maintain role'
runs-on: ubuntu-latest
steps:
- name: 'Check permission'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ACTOR: ${{ github.actor }}
REPO: ${{ github.repository }}
run: |
PERMISSION=$(gh api "repos/$REPO/collaborators/$ACTOR/permission" --jq '.permission')
echo "Permission level for $ACTOR: $PERMISSION"

case "$PERMISSION" in
maintain|admin)
echo "Access granted: $ACTOR has '$PERMISSION' permission."
;;
*)
echo "Access denied: $ACTOR has '$PERMISSION' permission, but 'maintain' or higher is required."
exit 1
;;
esac
55 changes: 55 additions & 0 deletions .github/workflows/spec-update-cleanup.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: spec update cleanup

on:
workflow_dispatch:
inputs:
service:
description: 'Which service the branch was created for'
type: choice
required: true
options:
- ai-api
- document-grounding
- orchestration
- prompt-registry
- sap-rpt
default: orchestration
ref:
description: 'Original branch or tag the branch was created from'
required: false
default: main
type: string
workflow_call:
inputs:
service:
description: 'Which service the branch was created for'
required: true
type: string
ref:
description: 'Original branch or tag the branch was created from'
required: false
default: main
type: string

jobs:
cleanup:
name: 'Delete Spec Update Branch'
needs: [auth]
runs-on: [ubuntu-latest]
permissions:
contents: write
env:
SERVICE: ${{ inputs.service }}
REF: ${{ inputs.ref }}
steps:
- name: 'Delete Branch'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
BRANCH="spec-update/$SERVICE/$REF"
if git ls-remote --exit-code --heads https://github.com/SAP/ai-sdk-java.git "$BRANCH" > /dev/null 2>&1; then
gh api "repos/SAP/ai-sdk-java/git/refs/heads/$BRANCH" -X DELETE
echo "Deleted branch: $BRANCH"
else
echo "Branch $BRANCH does not exist, nothing to delete."
fi
114 changes: 57 additions & 57 deletions .github/workflows/spec-update.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
name: "Spec File Update Workflow"
run-name: "Spec File Update Workflow: ${{ github.event.inputs.file }}-${{ github.event.inputs.file-ref }}"
name: 'Spec File Update Workflow'
run-name: 'Spec File Update Workflow: ${{ github.event.inputs.service }}-${{ github.event.inputs.ref }}'

on:
workflow_dispatch:
inputs:
file:
description: "Which spec file to update"
service:
description: 'Which spec file to update'
type: choice
required: false
options:
Expand All @@ -15,13 +15,13 @@ on:
- prompt-registry
- sap-rpt
default: orchestration
file-ref:
description: "Branch or tag to checkout the spec file from"
ref:
description: 'Branch or tag to checkout the spec file from'
required: false
default: main
type: string
create-pr:
description: "Create a pull request after updating the spec file"
description: 'Create a pull request after updating the spec file'
required: false
default: true
type: boolean
Expand All @@ -35,8 +35,8 @@ env:

jobs:
generate:
name: "Download, Generate, Compile and Push"
runs-on: [ ubuntu-latest ]
name: 'Download, Generate, Compile and Push'
runs-on: [ubuntu-latest]
permissions:
pull-requests: write
contents: write
Expand All @@ -47,54 +47,54 @@ jobs:
compilation_result: ${{ steps.compile.outputs.compilation_result }}
test_result: ${{ steps.compile.outputs.test_result }}
env:
API_BASE_URL: "https://github.tools.sap/api/v3/repos"
CHOICE: ${{ github.event.inputs.file }}
REF: ${{ github.event.inputs.file-ref }}
API_BASE_URL: 'https://github.tools.sap/api/v3/repos'
SERVICE: ${{ github.event.inputs.service }}
REF: ${{ github.event.inputs.ref }}
CREATE_PR: ${{ github.event.inputs.create-pr }}
steps:
- name: "Checkout repository"
- name: 'Checkout repository'
uses: actions/checkout@v6
with:
token: ${{ secrets.BOT_SDK_JS_FOR_DOCS_REPO_PR }}

- name: "Determine PR base"
- name: 'Determine PR base'
id: pr_base
# If updating orchestration and orchestration-staging exists on remote, use it as PR base.
run: |
BASE=main
if [ "${{ env.CHOICE }}" = "orchestration" ] && [ -n "$(git ls-remote --heads origin orchestration-staging)" ]; then
if [ "${{ env.SERVICE }}" = "orchestration" ] && [ -n "$(git ls-remote --heads origin orchestration-staging)" ]; then
BASE=orchestration-staging
fi
echo "PR base: $BASE"
echo "BASE=$BASE" >> "$GITHUB_OUTPUT"

- name: "Setup Java"
- name: 'Setup Java'
uses: actions/setup-java@v5
with:
distribution: "sapmachine"
distribution: 'sapmachine'
java-version: ${{ env.JAVA_VERSION }}
cache: 'maven'

- name: "Restore Dependencies"
- name: 'Restore Dependencies'
id: restore-dependencies
uses: actions/cache/restore@v5
with:
key: ${{ env.MAVEN_CACHE_KEY }}
path: ${{ env.MAVEN_CACHE_DIR }}

- name: "Checkout or Create Branch"
- name: 'Checkout or Create Branch'
id: branch
env:
BASE: ${{ steps.pr_base.outputs.BASE }}
CHOICE: ${{ env.CHOICE }}
SERVICE: ${{ env.SERVICE }}
REF: ${{ env.REF }}
run: |
BRANCH="spec-update/$CHOICE/$REF"
BRANCH="spec-update/$SERVICE/$REF"

# try to fetch the base and the target branch (ignore failures if missing)
git fetch --no-tags --depth=1 origin "$BASE" || true
git fetch origin "$BRANCH" || true

# if remote target branch exists, base the local branch on it
if git ls-remote --heads origin "$BRANCH" | grep -q "refs/heads/$BRANCH"; then
git checkout -B "$BRANCH" "origin/$BRANCH"
Expand All @@ -106,15 +106,15 @@ jobs:
git checkout -B "$BRANCH"
fi
fi

echo "branch=$BRANCH" >> "$GITHUB_OUTPUT"

- name: "Download specification file"
- name: 'Download specification file'
id: download
env:
GH_ENTERPRISE_TOKEN: ${{ secrets.GH_TOOLS_TOKEN }}
run: |
case $CHOICE in
case $SERVICE in
core)
API_URL="$API_BASE_URL/cloudsdk/cloud-sdk-java-tests/contents/aicore.yaml?ref=$REF"
FILE_PATH='core/src/main/resources/spec/aicore.yaml'
Expand All @@ -136,12 +136,12 @@ jobs:
FILE_PATH='foundation-models/sap-rpt/src/main/resources/spec/sap-rpt-1_openapi.json'
;;
esac

echo "Downloading $CHOICE specification file from $API_URL ..."

gh api $API_URL -H "Accept: application/vnd.github.raw" > $FILE_PATH

- name: "Exit if there are no spec changes"
echo "Downloading $SERVICE specification file from $API_URL ..."

gh api "$API_URL" -H "Accept: application/vnd.github.raw" > $FILE_PATH

- name: 'Exit if there are no spec changes'
id: spec_diff
env:
GH_TOKEN: ${{ secrets.BOT_SDK_JS_FOR_DOCS_REPO_PR }}
Expand All @@ -153,27 +153,27 @@ jobs:
else
echo "No spec changes detected. Checking status of previous run."
echo "spec_diff=false" >> "$GITHUB_OUTPUT"

# The current run of this workflow
CURRENT_RUN=${{ github.run_id }}

# name must match the workflow run-name pattern above
RUN_NAME="Spec File Update Workflow: $CHOICE-$REF"
RUN_NAME="Spec File Update Workflow: $SERVICE-$REF"
echo "Run name used for search: $RUN_NAME"

# Get the most recent completed run of this workflow with respect to the same feature branch
PREVIOUS_RUN=$(gh run list \
--workflow "${{ github.workflow }}" \
--branch main \
--json databaseId,status,conclusion,displayTitle \
--jq "map(select(.databaseId != ${CURRENT_RUN} and (.displayTitle | contains(\"${RUN_NAME}\")))) | .[0]")

echo "Previous run: $PREVIOUS_RUN"

if [ -n "$PREVIOUS_RUN" ] && [ "$PREVIOUS_RUN" != "null" ]; then
CONCLUSION=$(echo "$PREVIOUS_RUN" | jq -r '.conclusion')
echo "Previous run conclusion: $CONCLUSION"

if [ "$CONCLUSION" = "failure" ]; then
echo "Previous run failed and there were no spec changes since, thus failing this run as well."
echo "prev_run_success=false" >> "$GITHUB_OUTPUT"
Expand All @@ -187,7 +187,7 @@ jobs:
fi
fi

- name: "Generate"
- name: 'Generate'
id: generate
if: steps.spec_diff.outputs.spec_diff == 'true'
run: |
Expand All @@ -197,7 +197,7 @@ jobs:
echo "generation_result=failure" >> "$GITHUB_OUTPUT"
fi

- name: "Compile and Test"
- name: 'Compile and Test'
id: compile
if: steps.spec_diff.outputs.spec_diff == 'true'
# Compilation can easily fail e.g. from re-namings and has to be fixed manually.
Expand All @@ -215,18 +215,18 @@ jobs:
echo "test_result=skipped" >> "$GITHUB_OUTPUT"
fi

- name: "Push changes"
- name: 'Push changes'
id: push
if: steps.spec_diff.outputs.spec_diff == 'true'
run: |
git config --global user.email "cloudsdk@sap.com"
git config --global user.name "SAP Cloud SDK Bot"
git add --all
git status
git commit -m "Update $CHOICE based on $REF"
git commit -m "Update $SERVICE based on $REF"
git push --set-upstream origin ${{ steps.branch.outputs.branch }}

- name: "Create PR"
- name: 'Create PR'
id: create-pr
if: ${{ env.CREATE_PR == 'true' && steps.spec_diff.outputs.spec_diff == 'true'}}
env:
Expand All @@ -238,27 +238,27 @@ jobs:
echo "An open PR already exists for this branch. Skipping PR creation."
exit 0
fi
PR_URL=$(gh pr create --base $BASE --head $BRANCH --title "feat: [DevOps] Update $CHOICE specification" --body "

PR_URL=$(gh pr create --base $BASE --head $BRANCH --title "feat: [DevOps] Update $SERVICE specification" --body "
## Context
Update $CHOICE specification file based on $REF.

Update $SERVICE specification file based on $REF.

This PR was created automatically by the [spec-update workflow](https://github.com/SAP/ai-sdk-java/actions/workflows/spec-update.yaml).
You can commit on top of this branch, but as long as this PR is open the action can't be re-run.

- Compilation outcome: ${{ steps.compile.outputs.compilation_result }}
- Test run outcome: ${{ steps.compile.outputs.test_result }}

Before merging, make sure to update tests and release notes, if necessary.

## Definition of Done

- [ ] Unit tests cover new classes
- [ ] Release notes updated
") && echo "pr_url=$PR_URL" >> "$GITHUB_OUTPUT"

- name: "Generate Job Summary"
- name: 'Generate Job Summary'
if: ${{ always() }}
env:
BRANCH: ${{ steps.branch.outputs.branch }}
Expand All @@ -272,11 +272,11 @@ jobs:
echo "|------|--------|" >> $GITHUB_STEP_SUMMARY
echo "| File Download | ${{ steps.download.outcome == 'success' && '✅' || '❌' }} ${{ steps.download.outcome }}" >> $GITHUB_STEP_SUMMARY
echo "| Spec File Changes | ${{ steps.spec_diff.outputs.spec_diff == 'true' && '🔄 Changes Detected' || '⏹️ No Changes' }}" >> $GITHUB_STEP_SUMMARY

if ${{ steps.spec_diff.outputs.spec_diff == 'false' }}; then
echo "| Outcome Previous Run | ${{ steps.spec_diff.outputs.prev_run_success == 'true' && '✅ (Current run succeeds as a result.)' || '❌ (Current run fails as a result.)' }}" >> $GITHUB_STEP_SUMMARY
fi

if ${{ steps.spec_diff.outputs.spec_diff == 'true' }}; then
echo "| Client Generation | ${{ steps.generate.outputs.generation_result == 'success' && '✅' || '❌' }} ${{ steps.generate.outputs.generation_result }}" >> $GITHUB_STEP_SUMMARY
echo "| Client Compilation | ${{ steps.compile.outputs.compilation_result == 'success' && '✅' || '❌' }} ${{ steps.compile.outputs.compilation_result }}" >> $GITHUB_STEP_SUMMARY
Expand All @@ -285,19 +285,19 @@ jobs:
echo "| Pull Request Creation | ${{ env.CREATE_PR == 'false' && '⏩ skipped' || '' }}${{ env.CREATE_PR == 'true' && steps.push.outcome == 'success' && '✅ [PR Link]($PR_URL)' || '' }}" >> $GITHUB_STEP_SUMMARY
fi

- name: "Fail if generation failed"
- name: 'Fail if generation failed'
if: steps.generate.outputs.generation_result == 'failure'
run: |
echo "Client generation failed. Please check the Generate step logs for details."
exit 1

- name: "Fail if no spec changes and previous run failed"
- name: 'Fail if no spec changes and previous run failed'
if: steps.spec_diff.outputs.prev_run_success == 'false'
run: |
echo "Previous run failed and there were no spec changes since, thus failing this run as well."
exit 1

- name: "Slack Notification"
- name: 'Slack Notification'
if: failure() && github.event.inputs.create-pr == 'true'
uses: slackapi/slack-github-action@v2.1.1
with:
Expand Down
Loading