Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
16016ca
docs: design spec for ANS integration into tutorials-ims via cds-aler…
jung-thomas Aug 3, 2026
7ded993
docs: implementation plan for ANS integration into tutorials-ims
jung-thomas Aug 3, 2026
8854f0e
feat(alerts): add cds-alert-notification plugin dep + alerts config b…
jung-thomas Aug 3, 2026
33d2851
feat(alerts): fail-open alerting helper gated on ALERTS_ENABLED
jung-thomas Aug 3, 2026
623dfa2
feat(alerts): raise PublishRejected on publish soft-reject
jung-thomas Aug 3, 2026
7f656a0
feat(alerts): raise ScheduledJobFailed from scheduler chokepoint (all…
jung-thomas Aug 3, 2026
bd09734
feat(alerting): wire RebuildDispatchFailed hook into rebuild-trigger.…
jung-thomas Aug 3, 2026
e4d8b9f
feat(alerts): provision alert-notification instance via MTA (minor bump)
jung-thomas Aug 3, 2026
e5f5cad
docs(alerts): observability doc + operator post-merge checklist
jung-thomas Aug 3, 2026
0eeff37
docs(alerts): add package-lock regen step to operator checklist
jung-thomas Aug 3, 2026
380210e
ci(alerts): auth 4 npm-ci jobs to private GitHub Packages via App token
jung-thomas Aug 3, 2026
23a8700
feat(alerts): consume plugin from private GitHub Packages instead of …
jung-thomas Aug 3, 2026
44dd55a
ci: retrigger checks now that @sap-tutorials/cds-alert-notification v…
jung-thomas Aug 3, 2026
f45b93e
ci: retrigger after GitHub App packages-read approval
jung-thomas Aug 3, 2026
0a977d6
ci: retrigger after granting tutorials-ims read access to the package
jung-thomas Aug 3, 2026
00469b1
ci(alerts): read GitHub Packages via built-in GITHUB_TOKEN (packages:…
jung-thomas Aug 3, 2026
4b0b077
ci(alerts): one-shot workflow to regenerate lockfile via GITHUB_TOKEN…
jung-thomas Aug 3, 2026
b931323
chore(alerts): add @sap-tutorials/cds-alert-notification to package-l…
github-actions[bot] Aug 3, 2026
979be8e
ci: run checks with lockfile now populated
jung-thomas Aug 3, 2026
f97acd3
ci(alerts): auth remaining PR-gating npm-ci jobs to GitHub Packages
jung-thomas Aug 3, 2026
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
11 changes: 9 additions & 2 deletions .deploy/mta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ ID: tutorials-ims
# Bump this on each release you deploy — it's the version shown by `cf mtas`
# and in the mtar filename (tutorials-ims_<version>.mtar). Deploy is manual:
# `cd .deploy && mbt build && cf deploy mta_archives/tutorials-ims_<version>.mtar -e ../deploy/<env>.mtaext -f`.
version: 1.9.0
version: 1.10.0

# Top-level parameters (overridable per-env via deploy/<env>.mtaext).
parameters:
Expand Down Expand Up @@ -138,6 +138,7 @@ modules:
- name: tutorials-cloud-logging
- name: tutorials-aicore
- name: tutorials-credstore
- name: tutorials-alert-notification

- name: tutorials-srv-qa
type: nodejs
Expand All @@ -157,7 +158,7 @@ modules:
- cp -r ../../hugo/assets ./hugo/assets
- cp -r ../../hugo/data ./hugo/data
- cp -r ../../hugo/i18n ./hugo/i18n
- bash -c "mkdir -p srv/jobs && mkdir -p srv/handlers && mkdir -p srv/lib/branch && mkdir -p srv/lib/runtime-config && mkdir -p srv/lib/prompts && mkdir -p srv/lib/kg && mkdir -p srv/mcp/prompts && cp ../../srv/lib/branch/condition.js ../../srv/lib/branch/engine.js ../../srv/lib/branch/ranker.js ../../srv/lib/branch/user-state.js ../../srv/lib/branch/loaders.js ../../srv/lib/branch/mission-detail.js ../../srv/lib/branch/slug-key.js ../../srv/lib/branch/decide.js ../../srv/lib/branch/joule-tool.js ../../srv/lib/branch/branch-telemetry.js ../../srv/lib/branch/group-by-alt.js ../../srv/lib/branch/profile-fields.js ../../srv/lib/branch/profile-override.js srv/lib/branch/ && cp ../../srv/lib/runtime-config/kg-settings.js ../../srv/lib/runtime-config/ui-events-settings.js ../../srv/lib/runtime-config/search-settings.js ../../srv/lib/runtime-config/navigator-settings.js ../../srv/lib/runtime-config/display-settings.js ../../srv/lib/runtime-config/tenant-settings.js srv/lib/runtime-config/ && cp ../../srv/lib/kg/on-demand-enqueue.js ../../srv/lib/kg/on-demand-cosine-rank.js srv/lib/kg/ && cp ../../srv/lib/credstore.js ../../srv/lib/secret-resolver.js ../../srv/lib/content-store.js ../../srv/lib/content-publish-session.js ../../srv/lib/resolve-tutorial-author.js ../../srv/lib/_tutorials-table.js ../../srv/lib/catalog-renderer.js ../../srv/lib/catalog-data.js ../../srv/lib/catalog-mission-hierarchy.js ../../srv/lib/chrome-shell.js ../../srv/lib/pipeline-log.js ../../srv/lib/legacy-id.js ../../srv/lib/embedding-pipeline.js ../../srv/lib/step-text-extractor.js ../../srv/lib/embedding-client.js ../../srv/lib/step-vectors.js ../../srv/lib/user-progress.js ../../srv/lib/co-completion.js ../../srv/lib/tutorial-centroid.js ../../srv/lib/tag-label-map.js ../../srv/lib/code-check-tool.js ../../srv/lib/code-check-prompt.js ../../srv/lib/code-check-handler.js ../../srv/lib/code-check-llm.js ../../srv/lib/code-check-step-loader.js ../../srv/lib/code-check-spec-publish.js ../../srv/lib/validate-answer-spec-publish.js ../../srv/lib/category-classifier.js ../../srv/lib/category-classifier-llm.js ../../srv/lib/category-seed-embeddings.js ../../srv/lib/build-catalog-categories.js ../../srv/lib/chat-settings-resolver.js ../../srv/lib/kg-extract.js ../../srv/lib/kg-queries.js ../../srv/lib/kg-projection.js ../../srv/lib/kg-similarity.js ../../srv/lib/kg-cycles.js ../../srv/lib/kg-graph-rebuild.js ../../srv/lib/kg-sparql-client.js ../../srv/lib/kg-merge-pair.js ../../srv/lib/kg-concept-loader.js ../../srv/lib/kg-neighborhood-cache.js ../../srv/lib/kg-neighborhood-merge.js ../../srv/lib/kg-neighborhood-full-helpers.js ../../srv/lib/kg-other-resources-loader.js ../../srv/lib/kg-stamp-meta-text.js ../../srv/lib/kg-tutorial-teaches-map.js ../../srv/lib/kg-resource-type-config.js ../../srv/lib/kg-meta-formatters.js ../../srv/lib/discovery-mission-categories.js ../../srv/lib/external-content-ttl.js ../../srv/lib/recompute-tutorial-progress-bulk-sql.js ../../srv/lib/youtube-fetcher.js ../../srv/lib/homepage-events-merger.js ../../srv/lib/homepage-rss-fetcher.js ../../srv/lib/rss-parse.js ../../srv/lib/community-blogs-fetcher.js ../../srv/lib/community-blog-source-defaults.js ../../srv/lib/community-blogs-classifier.js ../../srv/lib/safe-fetch.js ../../srv/lib/curl-transport.js ../../srv/lib/khoros-transport.js ../../srv/lib/explainer-generator.js ../../srv/lib/_token-cost.js ../../srv/lib/metrics.js ../../srv/lib/relevance-classifier.js ../../srv/lib/relevance-seed-embeddings.js ../../srv/lib/relevance-keyword-rules.js ../../srv/lib/canonicalize-link.js ../../srv/lib/detect-language-en.js ../../srv/lib/kg-community-coverage.js srv/lib/ && cp ../../srv/handlers/categories-after-hooks.js ../../srv/handlers/completion-path-items-altgroup.js srv/handlers/ && mkdir -p srv && cp ../../srv/content-moderation-service.js srv/ && cp ../../srv/jobs/consolidate-concepts-job.js ../../srv/jobs/extract-concepts-job.js ../../srv/jobs/job-lock.js ../../srv/jobs/secret-expiry-check.js ../../srv/jobs/homepage-link-health.js ../../srv/jobs/kg-ondemand-job.js ../../srv/jobs/community-blogs-fetch-job.js ../../srv/jobs/community-blogs-classify-job.js ../../srv/jobs/fetch-news-job.js srv/jobs/ && cp ../../srv/lib/prompts/explainer-verb.md ../../srv/lib/prompts/explainer-shelf.md ../../srv/lib/prompts/explainer-shelf-entry.md ../../srv/lib/prompts/community-blogs-classifier.md srv/lib/prompts/ && cp ../../srv/mcp/prompts/summarize_mission_for_beginner.md ../../srv/mcp/prompts/generate_lab_exercise.md ../../srv/mcp/prompts/explain_concept.md ../../srv/mcp/prompts/suggest_learning_path.md srv/mcp/prompts/"
- bash -c "mkdir -p srv/jobs && mkdir -p srv/handlers && mkdir -p srv/lib/branch && mkdir -p srv/lib/runtime-config && mkdir -p srv/lib/prompts && mkdir -p srv/lib/kg && mkdir -p srv/mcp/prompts && cp ../../srv/lib/branch/condition.js ../../srv/lib/branch/engine.js ../../srv/lib/branch/ranker.js ../../srv/lib/branch/user-state.js ../../srv/lib/branch/loaders.js ../../srv/lib/branch/mission-detail.js ../../srv/lib/branch/slug-key.js ../../srv/lib/branch/decide.js ../../srv/lib/branch/joule-tool.js ../../srv/lib/branch/branch-telemetry.js ../../srv/lib/branch/group-by-alt.js ../../srv/lib/branch/profile-fields.js ../../srv/lib/branch/profile-override.js srv/lib/branch/ && cp ../../srv/lib/runtime-config/kg-settings.js ../../srv/lib/runtime-config/ui-events-settings.js ../../srv/lib/runtime-config/search-settings.js ../../srv/lib/runtime-config/navigator-settings.js ../../srv/lib/runtime-config/display-settings.js ../../srv/lib/runtime-config/tenant-settings.js srv/lib/runtime-config/ && cp ../../srv/lib/kg/on-demand-enqueue.js ../../srv/lib/kg/on-demand-cosine-rank.js srv/lib/kg/ && cp ../../srv/lib/credstore.js ../../srv/lib/secret-resolver.js ../../srv/lib/content-store.js ../../srv/lib/content-publish-session.js ../../srv/lib/resolve-tutorial-author.js ../../srv/lib/_tutorials-table.js ../../srv/lib/catalog-renderer.js ../../srv/lib/catalog-data.js ../../srv/lib/catalog-mission-hierarchy.js ../../srv/lib/chrome-shell.js ../../srv/lib/pipeline-log.js ../../srv/lib/legacy-id.js ../../srv/lib/embedding-pipeline.js ../../srv/lib/step-text-extractor.js ../../srv/lib/embedding-client.js ../../srv/lib/step-vectors.js ../../srv/lib/user-progress.js ../../srv/lib/co-completion.js ../../srv/lib/tutorial-centroid.js ../../srv/lib/tag-label-map.js ../../srv/lib/code-check-tool.js ../../srv/lib/code-check-prompt.js ../../srv/lib/code-check-handler.js ../../srv/lib/code-check-llm.js ../../srv/lib/code-check-step-loader.js ../../srv/lib/code-check-spec-publish.js ../../srv/lib/validate-answer-spec-publish.js ../../srv/lib/category-classifier.js ../../srv/lib/category-classifier-llm.js ../../srv/lib/category-seed-embeddings.js ../../srv/lib/build-catalog-categories.js ../../srv/lib/chat-settings-resolver.js ../../srv/lib/kg-extract.js ../../srv/lib/kg-queries.js ../../srv/lib/kg-projection.js ../../srv/lib/kg-similarity.js ../../srv/lib/kg-cycles.js ../../srv/lib/kg-graph-rebuild.js ../../srv/lib/kg-sparql-client.js ../../srv/lib/kg-merge-pair.js ../../srv/lib/kg-concept-loader.js ../../srv/lib/kg-neighborhood-cache.js ../../srv/lib/kg-neighborhood-merge.js ../../srv/lib/kg-neighborhood-full-helpers.js ../../srv/lib/kg-other-resources-loader.js ../../srv/lib/kg-stamp-meta-text.js ../../srv/lib/kg-tutorial-teaches-map.js ../../srv/lib/kg-resource-type-config.js ../../srv/lib/kg-meta-formatters.js ../../srv/lib/discovery-mission-categories.js ../../srv/lib/external-content-ttl.js ../../srv/lib/recompute-tutorial-progress-bulk-sql.js ../../srv/lib/youtube-fetcher.js ../../srv/lib/homepage-events-merger.js ../../srv/lib/homepage-rss-fetcher.js ../../srv/lib/rss-parse.js ../../srv/lib/community-blogs-fetcher.js ../../srv/lib/community-blog-source-defaults.js ../../srv/lib/community-blogs-classifier.js ../../srv/lib/safe-fetch.js ../../srv/lib/curl-transport.js ../../srv/lib/khoros-transport.js ../../srv/lib/explainer-generator.js ../../srv/lib/_token-cost.js ../../srv/lib/metrics.js ../../srv/lib/alerting.js ../../srv/lib/relevance-classifier.js ../../srv/lib/relevance-seed-embeddings.js ../../srv/lib/relevance-keyword-rules.js ../../srv/lib/canonicalize-link.js ../../srv/lib/detect-language-en.js ../../srv/lib/kg-community-coverage.js srv/lib/ && cp ../../srv/handlers/categories-after-hooks.js ../../srv/handlers/completion-path-items-altgroup.js srv/handlers/ && mkdir -p srv && cp ../../srv/content-moderation-service.js srv/ && cp ../../srv/jobs/consolidate-concepts-job.js ../../srv/jobs/extract-concepts-job.js ../../srv/jobs/job-lock.js ../../srv/jobs/secret-expiry-check.js ../../srv/jobs/homepage-link-health.js ../../srv/jobs/kg-ondemand-job.js ../../srv/jobs/community-blogs-fetch-job.js ../../srv/jobs/community-blogs-classify-job.js ../../srv/jobs/fetch-news-job.js srv/jobs/ && cp ../../srv/lib/prompts/explainer-verb.md ../../srv/lib/prompts/explainer-shelf.md ../../srv/lib/prompts/explainer-shelf-entry.md ../../srv/lib/prompts/community-blogs-classifier.md srv/lib/prompts/ && cp ../../srv/mcp/prompts/summarize_mission_for_beginner.md ../../srv/mcp/prompts/generate_lab_exercise.md ../../srv/mcp/prompts/explain_concept.md ../../srv/mcp/prompts/suggest_learning_path.md srv/mcp/prompts/"
- bash -c "node -e \"const p=require('./package.json'); p.dependencies=Object.assign(p.dependencies||{},{cheerio:'^1.2.0','@sap-ai-sdk/foundation-models':'^2.10.0'}); require('fs').writeFileSync('./package.json', JSON.stringify(p,null,2));\""
properties:
EXPOSE_CAP_UI: false
Expand Down Expand Up @@ -421,3 +422,9 @@ resources:
service: autoscaler
service-plan: standard
service-name: tutorials-autoscaler

- name: tutorials-alert-notification
type: org.cloudfoundry.managed-service
parameters:
service: alert-notification
service-plan: standard
6 changes: 5 additions & 1 deletion .github/workflows/api-docs-drift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm
- run: npm ci
- name: Install dependencies
run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.PACKAGES_READ_TOKEN || secrets.GITHUB_TOKEN }}
- name: Check /api-docs/ YAML ↔ testing-endpoints.md drift
# #1040 follow-up. Every row in hugo/data/api_endpoints.yaml must
# also appear (verbatim path OR every driftMarker) in the internal
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/cds-build-staging-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand All @@ -30,7 +31,10 @@ jobs:
# `cds build --production` invokes the cds-compiler which lives in
# @sap/cds-dk (devDependency). `npm ci` ensures it's available.
# ~30s cold; ~5s with cache.
- run: npm ci
- name: Install dependencies
run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.PACKAGES_READ_TOKEN || secrets.GITHUB_TOKEN }}
- name: Run CDS build staging check
# Approach: regenerate the artifacts via `cds build --production`,
# then `git diff --exit-code` against the staged outputs. Any
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/e2e-coverage-nudge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
steps:
- uses: actions/checkout@v4
with:
Expand All @@ -32,7 +33,10 @@ jobs:
with:
node-version: '22'
cache: npm
- run: npm ci
- name: Install dependencies
run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.PACKAGES_READ_TOKEN || secrets.GITHUB_TOKEN }}
- name: Run e2e coverage nudge (advisory)
env:
E2E_NUDGE_BASE: origin/${{ github.base_ref }}
Expand Down
46 changes: 46 additions & 0 deletions .github/workflows/regen-alerts-lockfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Regenerate lockfile (alerts dep)

# One-shot helper: resolves @sap-tutorials/cds-alert-notification from the
# private GitHub Packages registry and writes it into package-lock.json, then
# commits the updated lockfile back to the branch. Uses the built-in
# GITHUB_TOKEN (packages:read to fetch the package, contents:write to push) —
# no PAT, no App key. Run via "Run workflow" against the PR branch, then delete
# this file once the lockfile is committed.

on:
workflow_dispatch: {}

permissions:
contents: write
packages: read

jobs:
regen-lock:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}

- uses: actions/setup-node@v4
with:
node-version: '22'
registry-url: 'https://npm.pkg.github.com'
scope: '@sap-tutorials'

- name: Resolve dep into package-lock.json
run: npm install --package-lock-only --no-audit --no-fund
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Commit updated lockfile
run: |
if git diff --quiet package-lock.json; then
echo "package-lock.json already up to date — nothing to commit."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add package-lock.json
git commit -m "chore(alerts): add @sap-tutorials/cds-alert-notification to package-lock.json [skip ci]"
git push origin HEAD:${{ github.ref_name }}
6 changes: 5 additions & 1 deletion .github/workflows/schema-drift-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '22' }
- run: npm ci
- name: Install dependencies
run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.PACKAGES_READ_TOKEN || secrets.GITHUB_TOKEN }}
- run: npx tsx scripts/check-qa-schema-drift.ts
6 changes: 5 additions & 1 deletion .github/workflows/srv-qa-cp-list-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand All @@ -33,6 +34,9 @@ jobs:
# `npm ci` is overkill (we only need tsx + the source tree). The
# check has no runtime SAP deps and doesn't touch gen/. But ci
# is the safe choice; ~30s on a warm cache.
- run: npm ci
- name: Install dependencies
run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.PACKAGES_READ_TOKEN || secrets.GITHUB_TOKEN }}
- name: Run srv-qa cp-list check
run: npx tsx scripts/check-srv-qa-cp-list.ts
3 changes: 3 additions & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand All @@ -39,6 +40,8 @@ jobs:
hugo version
- name: Install dependencies
run: npm ci --no-audit --no-fund
env:
NODE_AUTH_TOKEN: ${{ secrets.PACKAGES_READ_TOKEN || secrets.GITHUB_TOKEN }}
- name: Setup nested workspaces (hugo-apps, app/explore) + rebuild native bindings
run: npm run setup
- name: Run unit tests
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/validate-api-docs-yaml.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,17 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm
- run: npm ci
- name: Install dependencies
run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.PACKAGES_READ_TOKEN || secrets.GITHUB_TOKEN }}
- name: Validate api-docs.yaml schema
# Phase 4.5 (#746). Schema-only check (no DB hit; ~1 sec).
# Rejects any PR that edits db/data/api-docs.yaml in a way that
Expand Down
2 changes: 2 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@sap-tutorials:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}
Loading
Loading