-
Notifications
You must be signed in to change notification settings - Fork 441
Add changelog generation script and tools #856
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| Write a changelog highlighting ONLY the rule changes based on the git commit messages and diffs provided. | ||
| Formatting, infrastructure, or similar non-rule changes should be omitted. | ||
|
|
||
| The rule numbers should always be referenced using angle brackets. For example, rule 211 should be written as <<211>>. | ||
|
|
||
| At the end of every changelog row, you should add a link to the related Pull Request in AsciiDoc format, like so: ^https://github.com/zalando/restful-api-guidelines/pull/<PR_NUMBER>[#PR_NUMBER]^ | ||
|
|
||
| If there is no relevant Pull Request, you should link to a commit in asciidoc format instead, like so: ^https://github.com/zalando/restful-api-guidelines/commit/<COMMIT_HASH>[SHORT_HASH]^ | ||
|
|
||
| Example changelog: | ||
|
|
||
| * `2021-12-09`: event id must not change in retry situations when producers <<211>>. | ||
| * `2021-11-24`: restructuring of the document and some rules. | ||
| * `2021-10-18`: new rule <<244>>. | ||
| * `2021-10-12`: improve clarity on {PATCH} usage in rule <<148>>. | ||
| * `2021-08-24`: improve clarity on {PUT} usage in rule <<148>>. | ||
| * `2021-08-24`: only use codes registered via IANA in rule <<243>>. | ||
| * `2021-08-17`: update formats per OpenAPI 3.1 in <<238>>. | ||
| * `2021-06-22`: <<238>> changed from {SHOULD} to {MUST}; consistency for rules around standards for data. | ||
| * `2021-06-03`: <<104>> with clear distinction of OpenAPI security schemes, favoring `bearer` to `oauth2`. | ||
| * `2021-06-01`: resolve uncertainties around 'occurred_at' semantics of <<event-metadata, event metadata>>. | ||
| * `2021-05-25`: <<172>> with <<114, API endpoint versioning>> as only custom media type usage exception. | ||
| * `2021-05-05`: define usage on resource-ids in {PUT} and {POST} in <<148>>. | ||
| * `2021-04-29`: improve clarity of <<133>>. | ||
| * `2021-03-19`: clarity on <<167>>. | ||
| * `2021-03-15`: <<242>> changed from {SHOULD} to {MUST}; improve clarity around <<203, event ordering>>. | ||
| * `2021-03-19`: best practice section <<cursor-based-pagination>> | ||
| * `2021-02-16`: define how to reference models outside the api in <<234>>. | ||
| * `2021-02-15`: improve guideline <<176>> -- clients must be prepared to not receive problem return objects. | ||
| * `2021-01-19`: more details for {GET-with-Body} and {DELETE-with-Body} (<<148>>). | ||
| * `2020-09-29`: include models for headers to be included by reference in API definitions (<<183>>) | ||
| * `2020-09-08`: add exception for legacy host names to <<224>> | ||
| * `2020-08-25`: change <<240>> from {MUST} to {SHOULD}, explain exceptions | ||
| * `2020-08-25`: add exception for `self` to <<143>> and <<134>>. | ||
| * `2020-08-24`: change "{MUST} avoid trailing slashes" to <<136>>. | ||
| * `2020-08-20`: change <<183>> from {MUST} to {SHOULD}, mention gateway-specific headers (which are not part of the public API). | ||
| * `2020-06-30`: add details to <<114>> | ||
| * `2020-05-19`: new sections about DELETE with query parameters and {DELETE-with-Body} in <<148>>. | ||
| * `2020-02-06`: new rule <<241>> | ||
| * `2020-02-05`: add Sunset header, clarify deprecation producedure (<<185>>, <<186>>, <<187>>, <<188>>, <<189>>, <<190>>, <<191>>) | ||
SmilyOrg marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| * `2020-01-21`: new rule <<240>> (as MUST, changed later to SHOULD) | ||
| * `2020-01-15`: change "Warning" to "Deprecation" header in <<189>>, <<190>>. | ||
SmilyOrg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,177 @@ | ||
| #!/bin/bash | ||
SmilyOrg marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| # Generate changelog entries from git history using AI analysis | ||
| # Usage: ./changelog.sh [OPTIONS] [YEAR|DATE] | ||
| # | ||
| # By default (no arguments): | ||
| # - Detects latest changelog entry date from chapters/changelog.adoc | ||
| # - Generates entries for commits since that date | ||
| # - Outputs filtered changelog entries only | ||
| # | ||
| # Options: | ||
| # --raw Show full AI analysis output instead of filtered entries | ||
| # --update Write new entries to chapters/changelog.adoc (prepend to rule-changes section) | ||
| # --since DATE Use explicit date (format: YYYY-MM-DD) instead of auto-detecting | ||
| # --year YEAR Generate for a specific year (format: YYYY) | ||
| # | ||
| # Examples: | ||
| # ./changelog.sh # Auto-detect and generate since last entry | ||
| # ./changelog.sh --raw # Auto-detect with full output | ||
| # ./changelog.sh --update # Auto-detect and update the changelog file | ||
| # ./changelog.sh --since 2025-01-01 # Generate since specific date | ||
| # ./changelog.sh --year 2025 # Generate for entire year 2025 | ||
| # ./changelog.sh 2025 --raw # Legacy: year as positional argument with --raw | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| REPO_ROOT="$(dirname "$SCRIPT_DIR")" | ||
| PROMPT_FILE="$SCRIPT_DIR/changelog.prompt" | ||
| CHANGELOG_FILE="$REPO_ROOT/chapters/changelog.adoc" | ||
|
|
||
| # Parse arguments | ||
| MODE="auto" # auto, year, since | ||
| PARAM="" | ||
| RAW_OUTPUT=false | ||
| UPDATE_FILE=false | ||
|
|
||
| # Handle legacy positional arguments first | ||
| if [[ ${#@} -gt 0 ]] && [[ "$1" =~ ^[0-9]{4}$ ]]; then | ||
| MODE="year" | ||
| PARAM="$1" | ||
| shift | ||
| fi | ||
|
|
||
| # Parse remaining options | ||
| while [[ ${#@} -gt 0 ]]; do | ||
| case "$1" in | ||
| --raw) | ||
| RAW_OUTPUT=true | ||
| ;; | ||
| --update) | ||
| UPDATE_FILE=true | ||
| ;; | ||
| --year) | ||
| MODE="year" | ||
| PARAM="${2:-}" | ||
| if [[ -z "$PARAM" ]]; then | ||
| echo "Error: --year requires a year argument (YYYY)" >&2 | ||
| exit 1 | ||
| fi | ||
| shift | ||
| ;; | ||
| --since) | ||
| MODE="since" | ||
| PARAM="${2:-}" | ||
| if [[ -z "$PARAM" ]]; then | ||
| echo "Error: --since requires a date argument (YYYY-MM-DD)" >&2 | ||
| exit 1 | ||
| fi | ||
| shift | ||
| ;; | ||
| *) | ||
| echo "Error: Unknown option: $1" >&2 | ||
| exit 1 | ||
| ;; | ||
| esac | ||
| shift | ||
| done | ||
|
|
||
| # Check dependencies | ||
| if ! command -v zllm &> /dev/null; then | ||
| echo "Error: 'zllm' command not found. Please install zllm to use this script." >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| if [[ ! -f "$PROMPT_FILE" ]]; then | ||
| echo "Error: Prompt file not found: $PROMPT_FILE" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Determine the date range for git log | ||
| cd "$REPO_ROOT" | ||
|
|
||
| case "$MODE" in | ||
| auto) | ||
| # Extract latest date from changelog.adoc | ||
| if [[ ! -f "$CHANGELOG_FILE" ]]; then | ||
| echo "Error: Changelog file not found: $CHANGELOG_FILE" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Look for first date entry after "== Rule Changes" section | ||
| LATEST_DATE=$(grep -oP "^\* \`\K[0-9]{4}-[0-9]{2}-[0-9]{2}" "$CHANGELOG_FILE" | head -1) | ||
SmilyOrg marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| if [[ -z "$LATEST_DATE" ]]; then | ||
| echo "Error: Could not find any date entries in changelog" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "Latest changelog entry: $LATEST_DATE" >&2 | ||
| AFTER_DATE="$LATEST_DATE" | ||
| ;; | ||
| year) | ||
| if ! [[ "$PARAM" =~ ^[0-9]{4}$ ]]; then | ||
| echo "Error: Invalid year format. Expected YYYY, got: $PARAM" >&2 | ||
| exit 1 | ||
| fi | ||
| AFTER_DATE="$PARAM-01-01" | ||
| BEFORE_DATE="$PARAM-12-31" | ||
| ;; | ||
| since) | ||
| if ! [[ "$PARAM" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then | ||
| echo "Error: Invalid date format. Expected YYYY-MM-DD, got: $PARAM" >&2 | ||
| exit 1 | ||
| fi | ||
| AFTER_DATE="$PARAM" | ||
| ;; | ||
| esac | ||
|
|
||
| # Get git log with diffs | ||
| if [[ -n "${BEFORE_DATE:-}" ]]; then | ||
| GIT_LOG=$(git log -p --after="$AFTER_DATE" --before="$BEFORE_DATE") | ||
| else | ||
| GIT_LOG=$(git log -p --after="$AFTER_DATE") | ||
| fi | ||
|
|
||
| if [[ -z "$GIT_LOG" ]]; then | ||
| echo "No commits found since $AFTER_DATE" >&2 | ||
| exit 0 | ||
| fi | ||
|
|
||
| # Pipe prompt and git log through zllm | ||
| OUTPUT=$(cat "$PROMPT_FILE" <(echo) <(echo "$GIT_LOG") | zllm) | ||
|
|
||
| # Extract changelog entries (lines starting with '*') | ||
| ENTRIES=$(echo "$OUTPUT" | grep '^\*' || true) | ||
|
|
||
| # Output or update | ||
| if [[ "$RAW_OUTPUT" == true ]]; then | ||
| echo "$OUTPUT" | ||
| elif [[ "$UPDATE_FILE" == true ]]; then | ||
| if [[ -z "$ENTRIES" ]]; then | ||
| echo "No changelog entries generated. Not updating file." >&2 | ||
| exit 0 | ||
| fi | ||
|
|
||
| # Create temporary file with new entries inserted after "== Rule Changes" header | ||
| # Split file into: header + new entries + rest | ||
| HEADER_LINE=$(grep -n "^== Rule Changes$" "$CHANGELOG_FILE" | cut -d: -f1) | ||
SmilyOrg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| { | ||
| # Read file up to (but not including) "== Rule Changes" | ||
| head -n "$((HEADER_LINE - 1))" "$CHANGELOG_FILE" | ||
| # Add the header and blank line | ||
| echo "== Rule Changes" | ||
| echo | ||
| # Add new entries | ||
| echo "$ENTRIES" | ||
SmilyOrg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| # Add existing entries (skip "== Rule Changes" line and the blank line after it) | ||
| tail -n +"$((HEADER_LINE + 2))" "$CHANGELOG_FILE" | ||
| } > "$CHANGELOG_FILE.tmp" | ||
|
|
||
| mv "$CHANGELOG_FILE.tmp" "$CHANGELOG_FILE" | ||
| echo "Updated $CHANGELOG_FILE with new entries" >&2 | ||
| else | ||
| echo "$ENTRIES" | ||
| fi | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.