Skip to content

Commit 072dbe6

Browse files
chore: merge main into release [skip ci]
2 parents 98b983a + a17afa8 commit 072dbe6

5 files changed

Lines changed: 234 additions & 47 deletions

File tree

.github/workflows/maven-build.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
name: Maven Build
1010

11+
permissions:
12+
contents: read
13+
1114
on:
1215
push:
1316
branches: [ 'main', 'dev' ]
@@ -19,7 +22,7 @@ jobs:
1922
runs-on: ubuntu-latest
2023
strategy:
2124
matrix:
22-
java: [ '8', '11' , '17' , '21' ,' 25' ]
25+
java: [ '8', '11' , '17' , '21' , '25' ]
2326
steps:
2427
- name: Checkout Source
2528
uses: actions/checkout@v5

.github/workflows/maven-publish.yml

Lines changed: 84 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@ on:
2121
jobs:
2222
build:
2323
runs-on: ubuntu-latest
24+
permissions:
25+
contents: read
2426
if: ${{ inputs.revision }}
2527
steps:
2628
- name: Validate version format
2729
run: |
2830
if ! echo "${{ inputs.revision }}" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
29-
echo "Error: version '${{ inputs.revision }}' does not match the required pattern major.minor.patch"
30-
exit 1
31+
echo "Error: version '${{ inputs.revision }}' does not match the required pattern major.minor.patch"
32+
exit 1
3133
fi
3234
3335
- name: Checkout Source
@@ -64,6 +66,7 @@ jobs:
6466
needs: build
6567
permissions:
6668
contents: write
69+
models: read
6770
steps:
6871
- name: Checkout Source
6972
uses: actions/checkout@v5
@@ -81,14 +84,90 @@ jobs:
8184
git push origin ${{ inputs.revision }}
8285
fi
8386
87+
- name: Generate Release Notes with Copilot
88+
env:
89+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
90+
run: |
91+
CURRENT_TAG="${{ inputs.revision }}"
92+
93+
# Find the previous tag (the one before the current tag)
94+
PREV_TAG=$(git describe --tags --abbrev=0 --exclude="${CURRENT_TAG}" HEAD 2>/dev/null || echo "")
95+
96+
# Collect commits between the previous tag and HEAD
97+
if [ -n "$PREV_TAG" ]; then
98+
COMMITS=$(git log --oneline "${PREV_TAG}..HEAD" 2>/dev/null || echo "No commits found")
99+
SINCE_LABEL="$PREV_TAG"
100+
else
101+
COMMITS=$(git log --oneline -50 2>/dev/null || echo "No commits found")
102+
SINCE_LABEL="the beginning"
103+
fi
104+
105+
# Export for Python (avoids shell-escaping issues with multiline content)
106+
export CURRENT_TAG_DATA="$CURRENT_TAG"
107+
export PREV_TAG_DATA="$SINCE_LABEL"
108+
export COMMITS_DATA="$COMMITS"
109+
110+
# Call GitHub Copilot via GitHub Models API and capture the summary
111+
SUMMARY=$(python3 << 'PYEOF'
112+
import json, os, urllib.request, sys
113+
114+
current_tag = os.environ['CURRENT_TAG_DATA']
115+
prev_tag = os.environ['PREV_TAG_DATA']
116+
commits = os.environ['COMMITS_DATA']
117+
token = os.environ['GH_TOKEN']
118+
119+
prompt = (
120+
f"Generate concise release notes for version {current_tag}.\n\n"
121+
f"Commits since {prev_tag}:\n{commits}\n\n"
122+
"Format the output as markdown with sections for New Features, Bug Fixes, "
123+
"and Other Changes (only include sections that have relevant commits). "
124+
"Be concise and clear."
125+
)
126+
127+
payload = json.dumps({
128+
"model": "gpt-4o",
129+
"messages": [{"role": "user", "content": prompt}]
130+
}).encode()
131+
132+
req = urllib.request.Request(
133+
"https://models.inference.ai.azure.com/chat/completions",
134+
data=payload,
135+
headers={
136+
"Content-Type": "application/json",
137+
"Authorization": f"Bearer {token}"
138+
}
139+
)
140+
141+
try:
142+
with urllib.request.urlopen(req) as resp:
143+
data = json.loads(resp.read())
144+
print(data["choices"][0]["message"]["content"])
145+
except Exception as e:
146+
print(f"Failed to generate summary via Copilot: {e}", file=sys.stderr)
147+
print(f"_Release notes generation failed. Raw commits since {prev_tag}:_\n\n```\n{commits}\n```")
148+
PYEOF
149+
)
150+
151+
# Append the summary (with version header) to release-notes.md
152+
NOTES_FILE="release-notes.md"
153+
if [ ! -f "$NOTES_FILE" ]; then
154+
printf "# Release Notes\n\n" > "$NOTES_FILE"
155+
fi
156+
printf "## v%s\n\n%s\n\n" "$CURRENT_TAG" "$SUMMARY" >> "$NOTES_FILE"
157+
158+
# Write the current release notes to a temp file for the Create Release step
159+
printf "%s" "$SUMMARY" > /tmp/current-release-notes.md
160+
161+
echo "Release notes generated and appended to $NOTES_FILE"
162+
84163
- name: Create Release
85164
run: |
86165
if gh release view "v${{ inputs.revision }}" >/dev/null 2>&1; then
87166
echo "Release v${{ inputs.revision }} already exists, skipping."
88167
else
89-
gh release create v${{ inputs.revision }} \
168+
gh release create ${{ inputs.revision }} \
90169
--title "v${{ inputs.revision }}" \
91-
--generate-notes \
170+
--notes-file /tmp/current-release-notes.md \
92171
--latest
93172
fi
94173
env:
@@ -109,7 +188,7 @@ jobs:
109188
run: |
110189
git config user.name "github-actions[bot]"
111190
git config user.email "github-actions[bot]@users.noreply.github.com"
112-
git add pom.xml
191+
git add pom.xml release-notes.md
113192
git diff --cached --quiet && echo "No changes to commit" || \
114193
git commit -m "chore: bump version to next patch after publishing ${{ inputs.revision }}" && git push
115194
Lines changed: 13 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,20 @@
11
# This workflow automatically merges the 'main' branch into 'dev' and 'release' branches
22
# whenever changes are pushed to 'main', without requiring manual confirmation.
33

4-
name: Merge Main to Dev and Release
4+
name: Merge Main to branches
55

66
on:
77
push:
88
branches:
99
- main
1010

11-
concurrency:
12-
group: merge-main-to-branches
13-
cancel-in-progress: false
14-
1511
jobs:
16-
merge-to-dev:
17-
name: Merge main → dev
18-
runs-on: ubuntu-latest
19-
permissions:
20-
contents: write
21-
steps:
22-
- name: Checkout Repository
23-
uses: actions/checkout@v5
24-
with:
25-
fetch-depth: 0
26-
token: ${{ secrets.GITHUB_TOKEN }}
27-
28-
- name: Merge main into dev
29-
run: |
30-
git config user.name "github-actions[bot]"
31-
git config user.email "github-actions[bot]@users.noreply.github.com"
32-
if ! git checkout dev; then
33-
echo "::error::Branch 'dev' does not exist. Skipping merge."
34-
exit 1
35-
fi
36-
if ! git merge --no-ff origin/main -m "chore: merge main into dev [skip ci]"; then
37-
echo "::error::Merge conflict detected when merging main into dev. Manual intervention required."
38-
exit 1
39-
fi
40-
git push origin dev
41-
42-
merge-to-release:
43-
name: Merge main → release
12+
merge-to-branch:
4413
runs-on: ubuntu-latest
14+
strategy:
15+
matrix:
16+
branch: [ 'dev', 'release' ]
17+
name: main -> ${{ matrix.branch }}
4518
permissions:
4619
contents: write
4720
steps:
@@ -51,16 +24,16 @@ jobs:
5124
fetch-depth: 0
5225
token: ${{ secrets.GITHUB_TOKEN }}
5326

54-
- name: Merge main into release
27+
- name: Merge main into ${{ matrix.branch }}
5528
run: |
5629
git config user.name "github-actions[bot]"
5730
git config user.email "github-actions[bot]@users.noreply.github.com"
58-
if ! git checkout release; then
59-
echo "::error::Branch 'release' does not exist. Skipping merge."
60-
exit 1
31+
if ! git checkout ${{ matrix.branch }}; then
32+
echo "[INFO] Branch '${{ matrix.branch }}' does not exist. Skipping merge."
33+
exit 0
6134
fi
62-
if ! git merge --no-ff origin/main -m "chore: merge main into release [skip ci]"; then
63-
echo "::error::Merge conflict detected when merging main into release. Manual intervention required."
35+
if ! git merge --no-ff origin/main -m "chore: merge main into ${{ matrix.branch }} [skip ci]"; then
36+
echo "[ERROR] Merge conflict detected when merging main into ${{ matrix.branch }}. Manual intervention required."
6437
exit 1
6538
fi
66-
git push origin release
39+
git push origin ${{ matrix.branch }}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# This workflow syncs every branch that belongs to the current project
2+
# from the upstream repository. It can be triggered manually or runs automatically
3+
# every 5 minutes.
4+
#
5+
# Step 1: The GitHub API is queried to determine whether the current repository
6+
# is a fork. If it is the upstream (not a fork), the job exits immediately.
7+
# Step 2: Each branch present in the fork is synced from the upstream parent.
8+
# Branches that exist only in the fork (not in upstream) are skipped.
9+
# If the fork's branch is ahead of upstream (i.e. has newer commits),
10+
# the sync is also skipped to avoid overwriting fork-only changes.
11+
# Step 3: The schedule runs every 5 minutes.
12+
13+
name: Sync Branches from Upstream
14+
15+
on:
16+
push:
17+
branches: [ 'main' , 'dev' , 'dev-1.x' ]
18+
schedule:
19+
- cron: '*/5 * * * *'
20+
21+
concurrency:
22+
group: sync-branches-from-upstream
23+
cancel-in-progress: true
24+
25+
jobs:
26+
sync:
27+
name: Sync branches from upstream
28+
runs-on: ubuntu-latest
29+
permissions:
30+
contents: write
31+
steps:
32+
- name: Check if this repository is a fork
33+
id: fork_check
34+
env:
35+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36+
run: |
37+
repo_info=$(gh api "repos/${{ github.repository }}")
38+
is_fork=$(echo "$repo_info" | jq -r '.fork')
39+
if [ "$is_fork" = "true" ]; then
40+
upstream_repo=$(echo "$repo_info" | jq -r '.parent.full_name // empty')
41+
if [ -z "$upstream_repo" ]; then
42+
echo "::error::Repository is marked as a fork but parent information is missing."
43+
exit 1
44+
fi
45+
echo "This repository is a fork of '${upstream_repo}'."
46+
echo "is_fork=true" >> "$GITHUB_OUTPUT"
47+
echo "upstream_repo=${upstream_repo}" >> "$GITHUB_OUTPUT"
48+
else
49+
echo "This repository is not a fork (it is the upstream). Nothing to sync."
50+
echo "is_fork=false" >> "$GITHUB_OUTPUT"
51+
fi
52+
53+
- name: Checkout Repository
54+
if: steps.fork_check.outputs.is_fork == 'true'
55+
uses: actions/checkout@v5
56+
with:
57+
fetch-depth: 0
58+
token: ${{ secrets.GITHUB_TOKEN }}
59+
60+
- name: Sync branches from upstream
61+
if: steps.fork_check.outputs.is_fork == 'true'
62+
env:
63+
GH_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
64+
run: |
65+
git config user.name "github-actions[bot]"
66+
git config user.email "github-actions[bot]@users.noreply.github.com"
67+
68+
upstream="${{ steps.fork_check.outputs.upstream_repo }}"
69+
echo "Upstream repository: $upstream"
70+
git remote add upstream "https://github.com/${upstream}.git"
71+
72+
echo "Fetching all refs from upstream..."
73+
git fetch upstream
74+
75+
echo "Fetching all refs from origin..."
76+
git fetch origin
77+
78+
# Collect all branches that exist in this project (origin), excluding HEAD pointer.
79+
origin_branches=$(git branch -r | grep '^ origin/' | grep -v '^ origin/HEAD' | sed 's|^ origin/||')
80+
81+
if [ -z "$origin_branches" ]; then
82+
echo "No branches found in the repository. Nothing to sync."
83+
exit 0
84+
fi
85+
86+
synced=0
87+
skipped=0
88+
failed=0
89+
90+
for branch in $origin_branches; do
91+
echo "---"
92+
# Only sync branches that also exist in upstream.
93+
if ! git ls-remote --exit-code upstream "refs/heads/${branch}" > /dev/null 2>&1; then
94+
echo "Branch '${branch}' does not exist in upstream – skipping."
95+
skipped=$((skipped + 1))
96+
continue
97+
fi
98+
99+
# If the origin and upstream branches point to the same commit, skip.
100+
origin_sha=$(git rev-parse "origin/${branch}")
101+
upstream_sha=$(git rev-parse "upstream/${branch}")
102+
if [ "$origin_sha" = "$upstream_sha" ]; then
103+
echo "Branch '${branch}' is already up to date."
104+
skipped=$((skipped + 1))
105+
continue
106+
fi
107+
108+
# If the fork branch is ahead of upstream (upstream is an ancestor of origin), skip.
109+
if git merge-base --is-ancestor "$upstream_sha" "$origin_sha"; then
110+
echo "Branch '${branch}' in fork is ahead of upstream – skipping."
111+
skipped=$((skipped + 1))
112+
continue
113+
fi
114+
115+
echo "Syncing branch '${branch}' from upstream..."
116+
if git push origin "upstream/${branch}:refs/heads/${branch}" --force-with-lease; then
117+
echo "Branch '${branch}' synced successfully."
118+
synced=$((synced + 1))
119+
else
120+
echo "::warning::Failed to push branch '${branch}'."
121+
failed=$((failed + 1))
122+
fi
123+
done
124+
125+
echo "==="
126+
echo "Sync complete: synced=${synced}, skipped=${skipped}, failed=${failed}"
127+
if [ "$failed" -gt 0 ]; then
128+
exit 1
129+
fi
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ jobs:
5555
5656
- name: Copy generated pages to wiki
5757
run: |
58+
# Remove all existing markdown files from wiki repo to ensure
59+
# pages for renamed or deleted classes are properly cleaned up
60+
find wiki-repo -maxdepth 1 -name '*.md' -type f -delete 2>/dev/null || true
5861
# Copy all generated markdown files to the wiki repo
5962
cp wiki-output/*.md wiki-repo/
6063
echo "Copied wiki pages to wiki repository"
@@ -73,4 +76,4 @@ jobs:
7376
git commit -m "Update wiki documentation - ${TIMESTAMP}"
7477
git push origin HEAD:master || git push origin HEAD:main
7578
echo "Wiki documentation updated successfully"
76-
fi
79+
fi

0 commit comments

Comments
 (0)