generate changelog json files on tag
This commit is contained in:
117
.github/scripts/generate_changelog.py
vendored
Normal file
117
.github/scripts/generate_changelog.py
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import git
|
||||
import argparse
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
||||
def get_tags(repo, branch_name):
|
||||
"""Returns sorted tags by date, filtered by branch name."""
|
||||
tags = [tag for tag in repo.tags if tag.name.startswith(branch_name)]
|
||||
# Sort tags in reverse chronological order based on the tag commit's date.
|
||||
tags = sorted(tags, key=lambda t: t.commit.committed_datetime, reverse=True)
|
||||
return tags
|
||||
|
||||
|
||||
def get_commits_between(repo, start_commit, end_commit):
|
||||
"""Get commit objects between two commits (excluding merges)."""
|
||||
commits = list(repo.iter_commits(f"{start_commit}..{end_commit}", no_merges=True))
|
||||
return commits
|
||||
|
||||
|
||||
def format_tag(tag, branch_name):
|
||||
"""Formats the tag as 'branch-YYYYMMDD-shortsha'."""
|
||||
commit_date = datetime.fromtimestamp(
|
||||
tag.commit.committed_date, timezone.utc
|
||||
).strftime("%Y%m%d")
|
||||
commit_hash = tag.commit.hexsha[:7] # Short commit hash
|
||||
return f"{branch_name}-{commit_date}-{commit_hash}"
|
||||
|
||||
|
||||
def generate_changelog(repo_path, changelog_path, branch_name):
|
||||
repo = git.Repo(repo_path)
|
||||
tags = get_tags(repo, branch_name)
|
||||
changelog_data = []
|
||||
|
||||
# No tags: output an "Initial Release" entry covering the entire history.
|
||||
if not tags:
|
||||
start_commit = repo.commit(repo.git.rev_list("--max-parents=0", "HEAD"))
|
||||
commits = get_commits_between(repo, start_commit.hexsha, "HEAD")
|
||||
date_str = datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
||||
release_entry = {
|
||||
"tag": "Initial Release",
|
||||
"date": date_str,
|
||||
"commits": []
|
||||
}
|
||||
for commit in commits:
|
||||
commit_entry = {
|
||||
"sha": commit.hexsha[:7],
|
||||
"message": commit.message.strip(),
|
||||
"author": commit.author.name,
|
||||
"date": commit.committed_datetime.strftime("%Y-%m-%d")
|
||||
}
|
||||
release_entry["commits"].append(commit_entry)
|
||||
changelog_data.append(release_entry)
|
||||
|
||||
else:
|
||||
# Process each pair of tags (newest tag down to the second oldest tag).
|
||||
# This will output a changelog entry for each tag that has commits
|
||||
# between it and the next tag.
|
||||
for i in range(len(tags) - 1):
|
||||
tag = tags[i] # Newest tag in the pair.
|
||||
next_tag = tags[i + 1] # Older tag
|
||||
|
||||
# Retrieve commits between the older and newer tag.
|
||||
commits = get_commits_between(repo, next_tag.commit.hexsha, tag.commit.hexsha)
|
||||
|
||||
if not commits:
|
||||
continue
|
||||
|
||||
# Use the commit date of the tag for the release entry.
|
||||
date_str = tag.commit.committed_datetime.strftime("%Y-%m-%d")
|
||||
formatted_tag = format_tag(tag, branch_name)
|
||||
release_entry = {
|
||||
"tag": formatted_tag,
|
||||
"date": date_str,
|
||||
"commits": []
|
||||
}
|
||||
for commit in commits:
|
||||
commit_entry = {
|
||||
"sha": commit.hexsha[:7],
|
||||
"message": commit.message.strip(),
|
||||
"author": commit.author.name,
|
||||
"date": commit.committed_datetime.strftime("%Y-%m-%d")
|
||||
}
|
||||
release_entry["commits"].append(commit_entry)
|
||||
changelog_data.append(release_entry)
|
||||
|
||||
# Write the changelog data as a JSON file.
|
||||
with open(changelog_path, "w", encoding="utf-8") as f:
|
||||
json.dump(changelog_data, f, indent=4)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate a changelog from git history and output JSON."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--repo_path", "-p", type=str, help="Path to the git repository", default="."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--changelog_path",
|
||||
"-f",
|
||||
type=str,
|
||||
default="./CHANGELOG.json",
|
||||
help="Path to the output JSON file (default: ./CHANGELOG.json)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--branch_name",
|
||||
"-b",
|
||||
type=str,
|
||||
default="master",
|
||||
help="Branch name to filter tags (default: master)",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
generate_changelog(args.repo_path, args.changelog_path, args.branch_name)
|
||||
44
.github/workflows/build.yml
vendored
44
.github/workflows/build.yml
vendored
@@ -55,7 +55,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
php: [8.4]
|
||||
php: [ 8.4 ]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -144,8 +144,6 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Ensure all commit history is available
|
||||
|
||||
- uses: bahmutov/npm-install@v1
|
||||
with:
|
||||
@@ -165,36 +163,6 @@ jobs:
|
||||
with_date: "true"
|
||||
with_branch: "true"
|
||||
|
||||
- name: Version tag
|
||||
uses: arabcoders/action-python-autotagger@master
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
repo_name: arabcoders/watchstate
|
||||
path: config/config.php
|
||||
regex: "'version'\\s\\=\\>\\s\\'(.+?)\\'\\,"
|
||||
|
||||
- name: Determine current branch
|
||||
id: branch
|
||||
run: |
|
||||
echo "BRANCH_NAME=${GITHUB_REF_NAME}" >> $GITHUB_ENV
|
||||
|
||||
- name: Fetch all tags
|
||||
run: git fetch --tags
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install gitpython
|
||||
|
||||
- name: Generate Changelog
|
||||
run: |
|
||||
python container/make_changelog.py --repo_path . --changelog_path ./CHANGELOG.md --branch_name $BRANCH_NAME
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
@@ -240,6 +208,14 @@ jobs:
|
||||
cache-from: type=gha, scope=${{ github.workflow }}
|
||||
cache-to: type=gha, scope=${{ github.workflow }}
|
||||
|
||||
- name: Version tag
|
||||
uses: arabcoders/action-python-autotagger@master
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
repo_name: arabcoders/watchstate
|
||||
path: config/config.php
|
||||
regex: "'version'\\s\\=\\>\\s\\'(.+?)\\'\\,"
|
||||
|
||||
dockerhub-sync-readme:
|
||||
runs-on: ubuntu-latest
|
||||
if: (github.event_name == 'push' && endsWith(github.ref, github.event.repository.default_branch)) || (github.event_name == 'workflow_dispatch' && github.event.inputs.update_readme == 'true')
|
||||
@@ -266,7 +242,7 @@ jobs:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # so we can see all tags + full history
|
||||
fetch-depth: 0 # so we can see all tags + full history
|
||||
|
||||
- name: Determine current branch
|
||||
id: branch
|
||||
|
||||
50
.github/workflows/changelog.yml
vendored
Normal file
50
.github/workflows/changelog.yml
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
name: Generate Changelog
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*" # Trigger on any tag push
|
||||
|
||||
jobs:
|
||||
generate-changelog:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Ensure we get all tags and history
|
||||
|
||||
- name: Set Up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install gitpython
|
||||
|
||||
- name: Get Branch Name from Tag
|
||||
id: branch_name
|
||||
run: |
|
||||
TAG_NAME=$(git describe --tags --abbrev=0)
|
||||
BRANCH_NAME=$(echo "$TAG_NAME" | cut -d '-' -f1)
|
||||
echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV
|
||||
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
|
||||
echo "Detected Tag: $TAG_NAME on Branch: $BRANCH_NAME"
|
||||
|
||||
- name: Generate Changelog JSON
|
||||
run: |
|
||||
python .github/scripts/generate_changelog.py --repo_path . --changelog_path ./CHANGELOG-${BRANCH_NAME}.json --branch_name $BRANCH_NAME
|
||||
|
||||
- name: Commit and Push to GitHub Pages
|
||||
run: |
|
||||
git config --global user.name "github-actions"
|
||||
git config --global user.email "github-actions@github.com"
|
||||
git checkout gh-pages || git checkout --orphan gh-pages
|
||||
git pull origin gh-pages || true
|
||||
mv CHANGELOG-*.json .
|
||||
git add CHANGELOG-*.json
|
||||
git commit -m "Update Changelog for $TAG_NAME"
|
||||
git push origin gh-pages
|
||||
@@ -1,69 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import git
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
|
||||
def get_tags(repo, branch_name):
|
||||
"""Returns sorted tags by date, filtered by branch name."""
|
||||
tags = [tag for tag in repo.tags if tag.name.startswith(branch_name)]
|
||||
tags = sorted(tags, key=lambda t: t.commit.committed_datetime, reverse=True)
|
||||
return tags
|
||||
|
||||
def get_commits_between(repo, start_commit, end_commit):
|
||||
"""Get commit messages between two commits (excluding merges)."""
|
||||
commits = list(repo.iter_commits(f"{start_commit}..{end_commit}", no_merges=True))
|
||||
return commits
|
||||
|
||||
def format_tag(tag, branch_name):
|
||||
"""Formats the tag as 'branch-latest-tag-date-hash'."""
|
||||
commit_date = datetime.fromtimestamp(tag.commit.committed_date, timezone.utc).strftime("%Y%m%d")
|
||||
commit_hash = tag.commit.hexsha[:7] # Short commit hash
|
||||
return f"{branch_name}-{commit_date}-{commit_hash}"
|
||||
|
||||
def generate_changelog(repo_path, changelog_path, branch_name):
|
||||
repo = git.Repo(repo_path)
|
||||
tags = get_tags(repo, branch_name)
|
||||
changelog_entries = []
|
||||
|
||||
if not tags:
|
||||
start_commit = repo.commit(repo.git.rev_list("--max-parents=0", "HEAD"))
|
||||
commits = get_commits_between(repo, start_commit.hexsha, "HEAD")
|
||||
date_str = datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
||||
changelog_entries.append(f"# {date_str} - Initial Release\n\n")
|
||||
|
||||
for commit in commits:
|
||||
changelog_entries.append(f"* {commit.summary}\n")
|
||||
else:
|
||||
for i in range(len(tags) - 1):
|
||||
tag = tags[i] # Newest tag
|
||||
next_tag = tags[i + 1] # Older tag
|
||||
|
||||
tag_commit = tag.commit.hexsha
|
||||
next_tag_commit = next_tag.commit.hexsha
|
||||
|
||||
commits = get_commits_between(repo, next_tag_commit, tag_commit)
|
||||
|
||||
if not commits:
|
||||
continue
|
||||
|
||||
date_str = datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
||||
formatted_tag = format_tag(tag, branch_name)
|
||||
changelog_entries.append(f"# {date_str} - {formatted_tag}\n\n")
|
||||
|
||||
for commit in commits:
|
||||
changelog_entries.append(f"* {commit.summary}\n")
|
||||
|
||||
changelog_entries.append("\n")
|
||||
|
||||
with open(changelog_path, "w", encoding="utf-8") as f:
|
||||
f.writelines(changelog_entries)
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate a changelog from git history.")
|
||||
parser.add_argument("--repo_path", "-p", type=str, help="Path to the git repository", default=".")
|
||||
parser.add_argument("--changelog_path", "-f", type=str, default="./CHANGELOG.md", help="Path to the output CHANGELOG.md file (default: ./CHANGELOG.md)")
|
||||
parser.add_argument("--branch_name", "-b", type=str, default="master", help="Branch name to filter tags (default: master)")
|
||||
args = parser.parse_args()
|
||||
|
||||
generate_changelog(args.repo_path, args.changelog_path, args.branch_name)
|
||||
Reference in New Issue
Block a user