Skip to content

chore: apply latest changesets #73285

chore: apply latest changesets

chore: apply latest changesets #73285

Workflow file for this run

name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
strategy:
# fail-fast: false # run all matrix build and not stop on the first failure
matrix:
os: [ubuntu-latest, windows-2025, macos-latest]
# https://github.com/actions/runner-images?tab=readme-ov-file#available-images
# not just the latest version of mac os also amd on Mac
# os: [ubuntu-latest, windows-2025, macos-13, macos-14, macos-14-large, macos-15, macos-latest-large]
node-version: [22.x, 24.x]
runs-on: ${{ matrix.os }}
environment: ci-secrets
timeout-minutes: 60
steps:
- name: Checkout code repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
- name: Enable long paths on Windows
if: runner.os == 'Windows'
shell: pwsh
run: |
# node-gyp extracts deeply nested OpenSSL headers during native module builds
# (e.g. better-sqlite3), which exceeds the default 260-char MAX_PATH limit.
# The registry key enables long-path support OS-wide; git config covers git ops.
git config --system core.longpaths true
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version: ${{ matrix.node-version }}
- name: Setup pnpm
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Cache pnpm modules
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
env:
cache-name: cache-pnpm-modules
with:
path: ~/.pnpm-store
key: ${{ matrix.os }}-build-${{ env.cache-name }}-${{ matrix.node-version }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ matrix.os }}-build-${{ env.cache-name }}-${{ matrix.node-version }}-
- name: Install pnpm modules
run: pnpm install --frozen-lockfile
- name: Cache Xenova model downloads
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: packages/fiori-docs-embeddings/.cache
key: xenova-model-cache-${{ matrix.os }}-${{ hashFiles('packages/fiori-docs-embeddings/package.json') }}
restore-keys: |
xenova-model-cache-${{ matrix.os }}-
- name: Run build
run: pnpm run build
env:
NX_CLOUD_ACCESS_TOKEN: ${{ github.event.pull_request.head.repo.full_name == github.repository && secrets.NX_CLOUD_ACCESS_TOKEN || '' }}
- name: Run lint on forks
if: github.event.pull_request.head.repo.full_name != github.repository
run: pnpm run lint
- name: Run unit tests
run: pnpm run test --tuiAutoExit
env:
NX_CLOUD_ACCESS_TOKEN: ${{ github.event.pull_request.head.repo.full_name == github.repository && secrets.NX_CLOUD_ACCESS_TOKEN || '' }}
- name: Check for changeset files
id: check_changeset_files
uses: andstor/file-existence-action@558493d6c74bf472d87c84eab196434afc2fa029 # v3
with:
files: '.changeset/[!README]*.md'
fail: false
- name: Validate changeset files if found
if: steps.check_changeset_files.outputs.files_exists == 'true'
run: pnpm changeset status
- name: Cache playwright browsers
id: cache-playwright-browsers
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: |
${{ runner.os == 'Windows' }}:
C:\Users\runneradmin\AppData\Local\ms-playwright
${{ runner.os != 'Windows' }}:
~/.cache/ms-playwright
key: playwright-browsers-chromium-os-${{ matrix.os }}-node-version-${{ matrix.node-version }}
- name: Install playwright chromium browsers
if: steps.cache-playwright-browsers.outputs.cache-hit != 'true'
run: npx playwright install chromium
- name: Run integration tests
run: pnpm run test:integration
env:
NX_CLOUD_ACCESS_TOKEN: ${{ github.event.pull_request.head.repo.full_name == github.repository && secrets.NX_CLOUD_ACCESS_TOKEN || '' }}
- name: Upload playwright reports
if: failure()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: playwright-reports-os-${{ matrix.os }}-node-version-${{ matrix.node-version }}
path: |
packages/*/playwright-report
!packages/*/node_modules
retention-days: 15
- name: Run SonarCloud scan
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '22.x'
shell: bash
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_HEAD_REF: ${{ github.event.pull_request.head.ref }}
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
run: |
echo "$PR_NUMBER" >> pr-event.txt
echo "$PR_HEAD_REF" >> pr-event.txt
echo "$PR_BASE_REF" >> pr-event.txt
- name: 'Prepare output artifact'
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '22.x'
shell: bash
run: touch output.tar && tar --exclude='./node_modules' --exclude='./dist' --exclude='./**/node_modules/**' --exclude='./**/dist/**' --exclude='./.git' --exclude 'output.tar' -czf output.tar .
- name: 'Upload sonar artifact'
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '22.x'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: sonar-artifact
path: |
pr-event.txt
output.tar
if-no-files-found: error
retention-days: 1
version:
# Run version job only on pushes to the main branch. The job depends on completion of the build job.
if: github.repository == 'SAP/open-ux-tools' && github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: build
environment: release
permissions:
contents: write
id-token: write
outputs:
changes: ${{ steps.changesetVersion.outputs.changes }} # map step output to job output
steps:
- name: Generate app token
id: app-token
uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Checkout code repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
token: ${{ steps.app-token.outputs.token }}
- name: Use Node.js 22.x
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version: 22.x
- name: Setup pnpm
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Cache pnpm modules
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
env:
cache-name: cache-pnpm-modules
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
- name: Install pnpm modules
run: pnpm install --frozen-lockfile
- name: Apply changesets
id: changesetVersion
run: |
echo ::set-output name=changes::$(pnpm ci:version 2>&1 | grep -q 'No unreleased changesets found' && echo 'false' || echo 'true')
git status
- name: Sync MCP manifest versions
if: steps.changesetVersion.outputs.changes == 'true'
run: node packages/fiori-mcp-server/scripts/sync-mcp-manifests.cjs
- name: Commit and push changes
if: steps.changesetVersion.outputs.changes == 'true'
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git status
git add -A
git status
git commit -m "chore: apply latest changesets" --no-verify || echo "No changesets found"
git log --pretty=oneline | head -n 10
git push
release:
# Run release job only on pushes to the main branch. The job depends on completion of the build job.
# This job needs to run after the version job commit has been merged - so check if that step returns 'false'
if: github.repository == 'SAP/open-ux-tools' && github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.version.outputs.changes == 'false'
runs-on: ubuntu-latest
needs: version
environment: npm-release
permissions:
id-token: write
contents: write
outputs:
published: ${{ steps.changesetPublish.outputs.published }}
publishedPackages: ${{ steps.changesetPublish.outputs.publishedPackages }}
steps:
- name: Checkout code repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Use Node.js 22.x
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version: 22.x
- name: Setup pnpm
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Cache pnpm modules
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
env:
cache-name: cache-pnpm-modules
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
- name: Install pnpm modules
run: pnpm install --frozen-lockfile
- name: Set instrumentation key in fiori-mcp-server
uses: jacobtomlinson/gha-find-replace@2ff30f644d2e0078fc028beb9193f5ff0dcad39e # v3
with:
include: packages/fiori-mcp-server/src/telemetry/index.ts
find: 'ApplicationInsightsInstrumentationKeyPLACEH0LDER'
replace: ${{ secrets.INSTRUMENTATION_KEY }}
regex: false
- name: Set instrumentation key in generator-odata-downloader
uses: jacobtomlinson/gha-find-replace@2ff30f644d2e0078fc028beb9193f5ff0dcad39e # v3
with:
include: packages/generator-odata-downloader/src/telemetry/index.ts
find: 'ApplicationInsightsInstrumentationKeyPLACEH0LDER'
replace: ${{ secrets.INSTRUMENTATION_KEY }}
regex: false
- name: Set instrumentation key in sap-systems-ext
uses: jacobtomlinson/gha-find-replace@2ff30f644d2e0078fc028beb9193f5ff0dcad39e # v3
with:
include: packages/sap-systems-ext/src/utils/telemetryHelper.ts
find: 'ApplicationInsightsInstrumentationKeyPLACEH0LDER'
replace: ${{ secrets.INSTRUMENTATION_KEY }}
regex: false
- name: Run build
run: pnpm run build
- name: 'Publish to npmjs'
id: changesetPublish
uses: changesets/action@6a0a831ff30acef54f2c6aa1cbbc1096b066edaf # v1.7.0
with:
publish: pnpm ci:publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Detect extension publication
if: steps.changesetPublish.outputs.published == 'true'
run: |
PUBLISHED=$(echo '${{ steps.changesetPublish.outputs.publishedPackages }}' | jq -r '.[].name')
# Extract the first package name matching sap-ux-*-ext
EXT_PKG=$(echo "$PUBLISHED" | grep -E '^sap-ux-.*-ext$' | head -n 1 || true)
if [ -n "$EXT_PKG" ]; then
echo "EXTENSION_UPDATED=true" >> $GITHUB_ENV
echo "EXT_PKG=$EXT_PKG" >> $GITHUB_ENV
# Strip 'sap-ux-' prefix to derive directory name
EXT_DIR_NAME=$(echo "$EXT_PKG" | sed 's/^sap-ux-//')
echo "EXT_DIR=packages/${EXT_DIR_NAME}" >> $GITHUB_ENV
else
echo "EXTENSION_UPDATED=false" >> $GITHUB_ENV
fi
- name: Read extension version
if: env.EXTENSION_UPDATED == 'true'
run: |
EXT_VERSION=$(jq -r '.version' "${{ env.EXT_DIR }}/package.json")
echo "EXT_VERSION=$EXT_VERSION" >> $GITHUB_ENV
- name: Package VSCode extension
if: env.EXTENSION_UPDATED == 'true'
run: pnpm --filter ${{ env.EXT_PKG }} ide-ext:package
- name: Create GitHub Release (extension)
if: env.EXTENSION_UPDATED == 'true'
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2
with:
tag_name: ${{ env.EXT_PKG }}@${{ env.EXT_VERSION }}
name: ${{ env.EXT_PKG }} v${{ env.EXT_VERSION }}
body: 'Extension release: ${{ env.EXT_PKG }} v${{ env.EXT_VERSION }}'
draft: true
prerelease: false
generate_release_notes: true
files: ${{ env.EXT_DIR }}/*.vsix
fail_on_unmatched_files: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare Slack notification message (published packages)
if: steps.changesetPublish.outputs.published == 'true'
run: |
# Random delimiter required to support multi-line environment variable value
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
echo "PUBLISHED_PACKAGES_MESSAGE<<$EOF" >> $GITHUB_ENV
# publishedPackages JSON format: '[{"name": "@sap-ux/axios-extension", "version": "1.0.2"}, {"name": "@sap-ux/fiori-freestyle-writer", "version": "0.15.12"}]'
echo "$(echo '${{ steps.changesetPublish.outputs.publishedPackages }}' | jq --raw-output 'map("*" + .name + "*" + " - " + "<https://www.npmjs.com/package/" + .name + "|" + .version + ">") | join("\\n")')" >> $GITHUB_ENV
echo "$EOF" >> $GITHUB_ENV
- name: Prepare Slack notification message (extension release only)
if: env.EXTENSION_UPDATED == 'true'
run: |
RELEASE_URL="https://github.com/${{ github.repository }}/releases/tag/${{ env.EXT_PKG }}@${{ env.EXT_VERSION }}"
echo "EXT_RELEASE_MESSAGE=:package: Extension *${{ env.EXT_PKG }}* v${{ env.EXT_VERSION }} released - <${RELEASE_URL}|View on GitHub>" >> $GITHUB_ENV
- name: Send Slack notification (published packages)
if: steps.changesetPublish.outputs.published == 'true'
uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
with:
payload: |
{"text": ":rocket: The following packages were published to npmjs.com:\n${{ env.PUBLISHED_PACKAGES_MESSAGE }}" }
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
- name: Send Slack notification (extension release)
if: env.EXTENSION_UPDATED == 'true'
uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
with:
payload: |
{"text": "${{ env.EXT_RELEASE_MESSAGE }}" }
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
publish-mcp-registry:
# Publish to MCP Registry after a successful npm release of fiori-mcp-server
if: |
github.repository == 'SAP/open-ux-tools' &&
github.event_name == 'push' &&
github.ref == 'refs/heads/main' &&
needs.release.outputs.published == 'true' &&
contains(needs.release.outputs.publishedPackages, '@sap-ux/fiori-mcp-server')
needs: release
uses: ./.github/workflows/publish-mcp-registry.yml
with:
dry_run: false
secrets: inherit
permissions:
id-token: write
contents: read