feat: add release note and webhook actions
All checks were successful
Aikido Security PR Check / Aikido Security Scan (pull_request) Successful in 46s
validate-shared-actions / validate-shared-actions (pull_request) Successful in 1m3s

This commit is contained in:
Kraft_Ruben_-_J._Schmalz_GmbH 2026-06-09 07:08:14 +02:00
parent 6a167350f0
commit b0f915be4c
4 changed files with 216 additions and 0 deletions

View file

@ -0,0 +1,39 @@
# generate-release-notes
Collects the git commit log between two refs and generates human-readable release notes using [Opencode](https://opencode.ai) with AWS Bedrock.
## Inputs
| Input | Required | Default | Description |
|-------|----------|---------|-------------|
| `bedrock-bearer-token` | Yes | — | AWS Bedrock bearer token for Opencode |
| `base-ref` | Yes | — | Base branch for git log comparison (e.g. `main` or `dev`) |
| `head-ref` | Yes | — | Head branch for git log comparison (e.g. `HEAD` or `dev`) |
| `section-title` | Yes | — | Title for the commits section in the generated markdown |
| `empty-message` | Yes | — | Message to include when no commits are found |
| `include-diff-stat` | No | `true` | Include a "Changed files" section with `git diff --stat` output |
## Outputs
| Output | Description |
|--------|-------------|
| `release-note` | The generated release notes as a markdown string |
## Usage
```yaml
- id: notes
uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/generate-release-notes@generate-release-notes-v1
with:
bedrock-bearer-token: ${{ secrets.BEDROCK_BEARER_TOKEN }}
base-ref: main
head-ref: HEAD
section-title: My Service
empty-message: No changes since last release.
```
## Notes
- Requires the repository to be checked out with enough history for the comparison (use `fetch-depth: 0` in the `checkout` action).
- Release notes are generated in German and categorised into 💡 Features, 🪲 Bugfixes, and 🧹 Wartung based on conventional commit prefixes.
- The output can be passed directly to the `publish-release-notes-via-webhook` action via `${{ steps.notes.outputs.release-note }}`.

View file

@ -0,0 +1,92 @@
name: Generate Release Notes
description: Collects git diff and generates release notes using GitHub Copilot CLI
inputs:
bedrock-bearer-token:
description: AWS Bedrock Bearer token for Opencode
required: true
base-ref:
description: Base branch name for git log comparison (e.g. "dev" or "main")
required: true
head-ref:
description: Head branch name for git log comparison (e.g. "HEAD" or "dev")
required: true
section-title:
description: Title for the commits section in the generated markdown
required: true
empty-message:
description: Message to include when no commits are found
required: true
include-diff-stat:
description: Include a "Changed files" section with git diff --stat output
default: 'true'
outputs:
release-note:
description: The generated release notes as a markdown string
value: ${{ steps.generate.outputs.release-note }}
runs:
using: composite
steps:
- name: Collect diff
shell: bash
run: |
git fetch origin ${{ inputs.base-ref }} ${{ inputs.head-ref }}
BASE_REF="origin/${{ inputs.base-ref }}"
HEAD_REF="${{ inputs.head-ref }}"
[[ "$HEAD_REF" != "HEAD" ]] && HEAD_REF="origin/$HEAD_REF"
BRANCH_COMMITS=$(git log $BASE_REF..$HEAD_REF \
--pretty=format:"- %h %s (%an, %ad)" \
--date=short)
{
echo "## ${{ inputs.section-title }}"
echo ""
echo "### Commits"
echo ""
if [ -z "$BRANCH_COMMITS" ]; then
echo "${{ inputs.empty-message }}"
else
echo "$BRANCH_COMMITS"
fi
} > commits.md
if [ "${{ inputs.include-diff-stat }}" = "true" ]; then
DIFF_STAT=$(git diff --stat $BASE_REF...$HEAD_REF)
{
echo ""
echo "### Changed files"
echo ""
if [ -z "$DIFF_STAT" ]; then
echo "No file changes found."
else
echo "$DIFF_STAT"
fi
} >> commits.md
fi
echo "--- commits.md ---"
cat commits.md
- name: Write Copilot output to Markdown
id: generate
shell: bash
env:
AWS_BEARER_TOKEN_BEDROCK: ${{ inputs.bedrock-bearer-token }}
PROMPT: "Erstelle Release Notes auf Basis der folgenden Commit-Liste. Release Notes bestehen aus einer Aufzählung mit jeweils einem Aufzählungspunkt pro Änderung. Die Aufzählung wird eingeleitet mit \"Folgende Änderungen wurden in Betrieb genommen:\". Die Änderungen sind nach Art der Änderung sortiert. Es gibt 3 Kategorien: \"💡 Features\", \"🪲 Bugfixes\" und \"🧹 Wartung\". Zu welcher Kategorie eine Änderung gehört, hängt vom Präfix der zugehörigen Commitnachricht ab. Wenn es zu einer Kategorie keine Änderungen gibt, wird sie weggelassen. Am Anfang jedes Punkts steht eine kurze, fettgedruckte Zusammenfassung der Änderung. Danach steht eine sachliche Beschreibung der Änderung in ganzen Sätzen. Sie richtet sich an ein nicht technisches Publikum, das aber mit der Materie vertraut ist (Product Owner, UX Designer, Team Lead). Beschränke dich daher aufs Wesentliche und verschweige technische Einzelheiten. Vermeide Abkürzungen, wenn du deren Bedeutung kennst. Bevorzuge aber die englischen Fachbegriffe. Am Ende jeder Änderung erwähne in Klammern den Autor sowie die referenzierten Ticketnummern, sofern vorhanden. Jira Tickets sollen mit Link eingefügt werden: https://jira.schmalz.com/browse/<TICKET_ID>"
run: |
curl -fsSL https://opencode.ai/install | bash
COMMITS=$(cat commits.md)
AWS_BEARER_TOKEN_BEDROCK=$AWS_BEARER_TOKEN_BEDROCK opencode run "$PROMPT $COMMITS" > release-notes.md
echo "--- release-notes.md ---"
cat release-notes.md
{
echo "release-note<<EOF"
cat release-notes.md
echo "EOF"
} >> "$GITHUB_OUTPUT"

View file

@ -0,0 +1,44 @@
# publish-release-notes-via-webhook
Sends release notes to a Microsoft Teams channel via a Power Automate webhook.
## Inputs
| Input | Required | Default | Description |
|-------|----------|---------|-------------|
| `service-name` | Yes | — | Name of the service included in the webhook payload |
| `release-note` | Yes | — | Release notes markdown content to publish |
| `request-url` | Yes | — | Power Automate webhook URL |
## Usage
```yaml
- uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/publish-release-notes-via-webhook@publish-release-notes-via-webhook-v1
with:
service-name: my-service
release-note: ${{ steps.notes.outputs.release-note }}
request-url: ${{ secrets.TEAMS_WEBHOOK_URL }}
```
## Webhook Payload
The action sends a `POST` request with the following JSON body:
```json
{
"servicename": "my-service",
"releasenote": "Folgende Änderungen wurden in Betrieb genommen:\n..."
}
```
| Field | Type | Description |
|-------|------|-------------|
| `servicename` | string | Value of the `service-name` input |
| `releasenote` | string | Value of the `release-note` input (markdown) |
The Power Automate flow must accept a `POST` request with `Content-Type: application/json` and handle both fields.
## Notes
- Designed to be used together with the `generate-release-notes` action, which exposes the `release-note` output.
- The webhook URL should be stored as a secret and never hardcoded in the workflow.

View file

@ -0,0 +1,41 @@
name: Publish Release Notes with Webhook
description: Sends generated release notes to a Teams webhook via Power Automate
inputs:
service-name:
description: Name of the service for the webhook payload
required: true
release-note:
description: The release notes markdown content to publish
required: true
request-url:
description: Power Automate webhook URL
required: true
runs:
using: composite
steps:
- name: Trigger Teams Webhook with release notes
shell: bash
env:
SERVICE_NAME: ${{ inputs.service-name }}
RELEASE_NOTE: ${{ inputs.release-note }}
REQUEST_URL: ${{ inputs.request-url }}
run: |
RELEASE_NOTE_CONTENT="$RELEASE_NOTE"
WEBHOOK_PAYLOAD=$(jq -n \
--arg servicename "$SERVICE_NAME" \
--arg releasenote "$RELEASE_NOTE_CONTENT" \
'{
"servicename": ($servicename),
"releasenote": ($releasenote)
}')
WEBHOOK_RESPONSE=$(curl -s -w "\n__HTTP_STATUS__:%{http_code}" -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
"$REQUEST_URL" \
-d "$WEBHOOK_PAYLOAD")
echo "Webhook response: $WEBHOOK_RESPONSE"